SFINAE: verificando a existência de uma função é interrompida quando a sobrecarga é movida para outros namespaces
Quero verificar a existência de uma função em um espaço de nome específico usando SFINAE. eu encontreiSFINAE para testar uma função livre de outro espaço para nome que faz o trabalho, mas há algumas coisas que eu não entendo.
Atualmente eu tenho esse código de trabalho, diretamente da pergunta vinculada:
// 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");
(aENABLE_FOO_BAR
macro é apenas para fins de teste, no meu código real não tenho essa macro disponível, caso contrário eu não estaria usando SFINAE)
No entanto, assim que eu colocodetail_overload::bar()
em qualquer outro espaço de nome (ajustando ousing
diretiva, conforme necessário), a detecção é interrompida silenciosamente e osstatic_assert
entra em açãoquandofoo::bar()
existe. Só funciona quando o "manequim"bar()
sobrecarga está diretamente no espaço para nome global, ou parte do::detail_overload
namespace (observe o global::
escopo).
// 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;
//...
Percebo que esse é o mesmo problema da pergunta a que vinculei e, como mencionado, já tenho uma solução funcional, mas o que não foi abordado é queporqueprecisamente isso acontece?
Como uma questão paralela, existe alguma maneira de obter a detecção correta de SFINAE sem poluir o namespace global combar()
ou umdetail_overload
namespace? Como você pode adivinhar nos exemplos que não funcionam, eu gostaria de agrupar tudo em um únicofeature_test
namespace.