3

次のテンプレートを検討してください。

template<class T>
void doStuff(const T& a)
    {
    if(std::is_copy_assignable<T>::value)
        {
        T x;
        x=a;
        printf("Hello\n");
        }
    else
        {
        printf("Goodbye\n");
        }
    }

これは、「Hello」部分がコピー代入不可の型に対して決して実行されないにもかかわらず、コンパイルに失敗します。代わりに何をすべきですか?

4

1 に答える 1

3

問題を解決するためのタグディスパッチベースの方法は次のとおりです。

template<class T>
void doStuffHelper(const T& a, std::true_type can_copy_assign)
{
  T x;
  x=a;
  printf("Hello\n");
}
template<class T>
void doStuffHelper(const T& a, std::false_type can_copy_assign)
{
  printf("Goodbye\n");
}
template<class T>
void doStuff(const T& a)
{
  return doStuffHelper( a, std::is_copy_assignable<T>() );
}

ここでは、動作するバージョンのみがコンパイルされます。の名前はcan_copy_assign単に説明のために存在します。要点は、 に基づいてオーバーライドしstd::is_copy_assignable<T>()、オーバーライド ディスパッチを使用して使用する実装を選択することです。

コードでは、ifブロックは のようになりますif(true)まだコンパイルする必要があるブロックのelse句。これは、使用されるメソッドが実行されなくても、有効でなければならないことを意味します。ifif(true)

タグ ディスパッチ ソリューションは、期待されるプロパティを持つ関数が、そのプロパティを使用するコードでコンパイルされるように配置します。

SFINAE を含む同様の方法を使用することもできますが、SFINAE には煩わしい複雑な問題がいくつかあるため、通常、可能であれば回避することが最善です。

于 2013-08-08T19:12:01.460 に答える