前の質問のフォローアップとして、明示的な特殊化を必要とするテンプレート関数の存在を検出しようとしています。
私の現在の作業コードは、非テンプレート関数を検出します (DyP の助けのおかげで)。依存する名前のルックアップを使用できるように少なくとも 1 つのパラメーターを取る場合:
// switch to 0 to test the other case
#define ENABLE_FOO_BAR 1
namespace foo {
#if ENABLE_FOO_BAR
int bar(int);
#endif
}
namespace feature_test {
namespace detail {
using namespace foo;
template<typename T> decltype(bar(std::declval<T>())) test(int);
template<typename> void test(...);
}
static constexpr bool has_foo_bar = std::is_same<decltype(detail::test<int>(0)), int>::value;
static_assert(has_foo_bar == ENABLE_FOO_BAR, "something went wrong");
}
(ENABLE_FOO_BAR
マクロはテスト目的のためのものです。私の実際のコードでは、そのようなマクロを利用できません。そうでなければ、SFINAE を使用しません)
これは、テンプレート引数がコンパイラによって自動的に推定できる場合、テンプレート関数でも完全に機能します。
namespace foo {
#if ENABLE_FOO_BAR
template<typename T> int bar(T);
#endif
}
ただし、明示的な特殊化が必要なテンプレート関数を検出しようとすると、存在するstatic_assert
場合にfoo::bar()
開始されます:
namespace foo {
#if ENABLE_FOO_BAR
template<typename T, typename U> T bar(U);
#endif
}
//...
// error: static assertion failed: something went wrong
明らかに、コンパイラはテンプレート引数を推測できないbar()
ため、検出は失敗します。呼び出しを明示的に特殊化して修正しようとしました:
template<typename T> decltype(bar<int, T>(std::declval<T>())) test(int);
// explicit specialization ^^^^^^^^
これは、存在する場合は正常に機能します (関数は正しく検出されます) が、存在しない場合foo::bar()
はすべてが崩壊します。foo::bar()
error: ‘bar’ was not declared in this scope
template<typename T> decltype(bar<int, T>(std::declval<T>())) test(int);
^
error: expected primary-expression before ‘int’
template<typename T> decltype(bar<int, T>(std::declval<T>())) test(int);
^
// lots of meaningless errors that derive from the first two
bar
コンパイラはそれがテンプレートであることを認識していないため、明示的な特殊化の試みが失敗したようです。
これを修正するために私が試みたすべてのことは割愛して、ポイントに直行します:インスタンス化するために明示的な特殊化を必要とするような関数の存在をどのように検出できますか?template<typename T, typename U> T bar(U);