C では、 std::enable_if は、特定の制約に基づいて条件付きでテンプレートを有効にするメタ関数です。最近、より簡潔な std::enable_if_t に置き換えられました。ただし、新しい構文を使用するために既存のコードを移植しようとすると、予期しない再定義エラーが発生するユーザーもいます。
サンプル コード
std:: を使用して作成された次のコードを考えてみましょう。 enable_if:
template<typename T, typename std::enable_if<std::is_same<int, T>::value>::type* = nullptr> void f() { } template<typename T, typename std::enable_if<std::is_same<double, T>::value>::type* = nullptr> void f() { }
このコードは、int と double の個別の特殊化を使用して、正常にコンパイルされます。ここで、std::enable_if_t 構文を使用してこれを書き直すとします。
template<typename T, typename = std::enable_if_t<std::is_same<int, T>::value>> void g() { } template<typename T, typename = std::enable_if_t<std::is_same<double, T>::value>> void g() { }
予期せぬエラー
予想に反して、この更新されたコードはコンパイルに失敗します。 GCC 5.2 を使用した場合reports:
error: redefinition of 'template<class T, class> void g()' void g() { }
説明
エラーは、std::enable_if_t が条件ではなく型を表すという事実にあります。テンプレート引数として使用すると、型制約が指定されます。元の std::enable_if の場合、2 番目のテンプレート パラメーターはポインター型ですが、std::enable_if_t バージョンでは、型のエイリアスになります。これにより、同じ型 (void()) を持つ 2 つの異なるテンプレート引数が生成されます。
Solution
この曖昧さを回避するには、2 番目のテンプレート パラメータが次のことを保証する必要があります。は一意の型制約を表します。これを実現する 1 つの方法は、ダミーのテンプレート パラメーターを使用することです。
template<typename T, typename U = std::enable_if_t<std::is_same<int, T>::value>> void g() { } template<typename T, typename U = std::enable_if_t<std::is_same<double, T>::value>> void g() { }
この場合、U は 2 つのテンプレート引数を区別するためだけに機能するダミー パラメーターです。この変更により、コードは正常にコンパイルされるようになります。
以上がテンプレート引数で std::enable_if_t を使用すると再定義エラーが発生するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。