0

私の実際のユースケースはさらにいくつかの引数を取りますが、これは次のように単純化されます:

template< typename Arg1 >
bool algorithm( Arg1&& p1, **p2 here** );

それだけで、Arg1 が何らかの形で崩壊し、何らかの参照になる可能性が高いことは明らかです。p1 はアルゴリズムの出力でもあるため、呼び出し元が左辺値を渡すことを選択した場合、関数は中断した場所を反映するように変更された元のパラメーターで戻ります。

ただし、p2 は同じタイプですが、変更されることはありません。したがって、実際には、正確さのために「const」プロミスを入れたいと思います。明らかに、Arg1 が参照であると推測される場合、それに const を追加することはできません。

だから私の解決策はこれです:

template< class T >
struct make_const_ref
{
typedef typename std::add_reference< typename std::add_const< typename std::remove_reference< T >::type >::type >::type type;
};

template< typename Arg1 >
bool algorithm( Arg1&& p1, typename make_const_ref<Arg1>::type p2 );

これは、いくつかの修飾子を削除してから const& を元に戻すために、ばかげた策略の束を通過します。

だから私の質問は:

1) これが最善の方法ですか?

2) これが失敗するコンテキストはありますか? 今のところ、それは私にはかなり良いようです。

4

1 に答える 1

0

驚くべき変更を 1 つ思いつくことができますが、完全な失敗にはなりません。2 番目のパラメーターは引数推定から無効になっているため、型は最初のパラメーターの型と正確に一致する必要がなくなりました。これにより、テンプレート引数が関数に指定されているかのように、暗黙的な変換を受け入れることができます。例:

struct Foo
{
    int value;

    operator int() const
    {
        return value;
    }
};

int main()
{
    algorithm(0, Foo{0});
}

一方、式:

template<typename Arg>
bool algorithm(const Arg& p1, const Arg2& p2)

algorithm(0, Foo{0})明示的でない限り、コンパイルに失敗しますalgorithm<int>(0, Foo{0})。完全一致のみを望んでいた場合、これは問題になる可能性があります。場合によっては、これが望ましい場合もあります。boost::clampは、意図的にこれを行っていることを認識している一例です。

ボーナス

これはあなたの質問へのコメントの一部に似ていますが、特性は単純化できます:

template<typename Type>
using const_ref_t = 
    typename std::add_const<
        typename std::add_lvalue_reference<Type>::type>::type;

std::add_lvalue_referenceは、すべての状況で必要なことを行います。

編集

これをコメントとして入れましたが、おそらくここに行くべきです。これはおそらく簡単です:

template<typename Arg1>
bool algorithm(Arg1&& p1, const typename std::remove_reference<Arg1>::type& p2)

あなたがやろうとしているのは、2番目のパラメーターの引数推定を無効にして、const-reference で取得することだけです。これはまさにそれをやっています。

于 2014-06-05T03:45:57.647 に答える