SFINAE を使用して、特定の名前空間に関数が存在するかどうかを確認したいと考えています。私はSFINAE が仕事をする別の名前空間からの自由な関数をテストすることを発見しましたが、私が理解していないことがいくつかあります。
現在、リンクされた質問から直接、この作業コードがあります:
// switch to 0 to test the other case
#define ENABLE_FOO_BAR 1
namespace foo {
#if ENABLE_FOO_BAR
int bar();
#endif
}
namespace detail_overload {
template<typename... Args> void bar(Args&&...);
}
namespace detail {
using namespace detail_overload;
using namespace foo;
template<typename T> decltype(bar()) test(T);
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 を使用しません)
detail_overload::bar()
ただし、他の名前空間を配置するとすぐに(必要に応じてusing
ディレクティブを調整します)、検出は静かに中断static_assert
され、when foo::bar()
exists が開始されます。「ダミー」bar()
オーバーロードがグローバル名前空間または名前空間の一部に直接ある場合にのみ機能します (グローバルスコープ::detail_overload
に注意してください)。::
// breaks
namespace feature_test {
namespace detail_overload {
template<typename... Args> void bar(Args&&...);
}
namespace detail {
using namespace detail_overload;
using namespace foo;
//...
// breaks
namespace feature_test {
template<typename... Args> void bar(Args&&...);
namespace detail {
using namespace foo;
//...
// breaks
namespace detail {
namespace detail_overload {
template<typename... Args> void bar(Args&&...);
}
using namespace detail_overload;
using namespace foo;
//...
// works
template<typename... Args> void bar(Args&&...);
namespace feature_test {
namespace detail {
using namespace foo;
//...
// works
namespace detail_overload {
template<typename... Args> void bar(Args&&...);
}
namespace feature_test {
namespace detail {
using namespace detail_overload;
using namespace foo;
//...
これは私がリンクした質問とまったく同じ問題であり、前述のようにすでに実用的な解決策があることを認識していますが、対処されていないのはなぜこれが正確に起こるのですか?
副次的な質問として、どちらかbar()
または名前空間でグローバル名前空間を汚染することなく、正しい SFINAE 検出を実現する方法はありdetail_overload
ますか? feature_test
動作しない例から推測できるように、すべてを 1 つの名前空間にきちんとまとめたいと思います。