【发布时间】:2013-02-15 09:14:12
【问题描述】:
以下程序在两个单独的命名空间(A 和 B)中定义了两个函数模板,A::foo<>() 和 B::foo<>()。这两个函数模板签名相同,仅在分配给它们的第二个模板参数的默认参数上有所不同。最终,它们的名字通过一对对应的using 声明进入main() 的范围:
#include <type_traits>
namespace A
{
template<
typename T,
typename = typename std::enable_if<
std::is_same<T, int>::value // Let this be condition C
>::type
>
void foo(T) { }
}
namespace B
{
template<
typename T,
typename = typename std::enable_if<
!std::is_same<T, int>::value // This is the negation of C
>::type
>
void foo(T) { }
}
int main() {
using A::foo;
using B::foo; // COMPILES: Is this legal?
foo(42); // Invokes A::foo(), non-ambiguous because of SFINAE
}
我希望第二个using 声明会在此处导致编译错误:毕竟,当我尝试在同一个命名空间中定义这两个模板时,我会得到这样的结果。
令我惊讶的是,我尝试过的每个编译器(GCC 4.7.2、GCC 4.8.0 beta、ICC 13.0.1、Clang 3.2)都会编译程序并调用A::foo()。
问题 #1:这是正确的吗?这可能是“不需要诊断”的情况吗?鼓励参考 C++11 标准。
现在考虑上述程序的这种变体,它基本上使用类而不是命名空间来实现相同的效果:
#include <type_traits>
struct X
{
template<
typename T,
typename = typename std::enable_if<
std::is_same<T, int>::value // Here is condition C again
>::type
>
static void foo(T) { }
};
struct Y
{
template<
typename T,
typename = typename std::enable_if<
!std::is_same<T, int>::value // And the negation of C again
>::type
>
static void foo(T) { }
};
struct Z : X, Y
{
using X::foo;
using Y::foo; // COMPILES: Is this legal?
};
int main() {
Z::foo(42); // Invokes X::foo(), non-ambiguous because of SFINAE
}
该程序也可以在上述所有编译器上编译,而我预计第二个 using 声明会导致编译器错误。
问题 #2:这是正确的吗?这可能是“不需要诊断”的情况吗?鼓励参考 C++11 标准。
【问题讨论】:
标签: c++ templates c++11 using-declaration