gpt4 book ai didi

c++ - 具有相同签名的模板不会导致编译器错误

转载 作者:搜寻专家 更新时间:2023-10-31 01:11:14 25 4
gpt4 key购买 nike

下面的程序定义了两个函数模板,A::foo<>()B::foo<>() ,在两个独立的命名空间中( AB )。这两个函数模板签名相同,仅在分配给它们第二个模板参数的默认参数上有所不同。最终,他们的名字被纳入了main()的范围。通过相应的一对 using声明:

#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 标准。

最佳答案

对于问题 #1:这似乎是允许的,因为没有禁止它的规则。如果 using 声明引入的函数与直接在 using 声明引入名称的命名空间中声明的函数冲突,C++11 标准在一条注释中提到了这一点。

§7.3.3[namespace.udecl]/14 中说:

If a function declaration in namespace scope or block scope has the same name and the same parameter types as a function introduced by a using-declaration, and the declarations do not declare the same function, the program is ill-formed. [...]

这是指定某种冲突无效的规范文本。

没有规范文本规定两个 using 声明不会以相同方式发生冲突,但请注意,两个 using 声明之间的类似冲突在声明点不无效。同段续:

[...] [ Note: Two using-declarations may introduce functions with the same name and the same parameter types. If, for a call to an unqualified function name, function overload resolution selects the functions introduced by such using-declarations, the function call is ill-formed. [ Example:

 namespace B { 
void f(int);
void f(double);
}
namespace C {
void f(int);
void f(double);
void f(char);
}

void h() {
using B::f; // B::f(int) and B::f(double)
using C::f; // C::f(int), C::f(double), and C::f(char)
f(’h’); // calls C::f(char)
f(1); // error: ambiguous: B::f(int) or C::f(int)?
void f(int); // f(int) conflicts with C::f(int) and B::f(int)
}

— end example ] — end note ]

对于问题 #2,描述类成员声明和类级别 using 声明之间冲突情况的类似规范文本在以下段落中,§7.3.3/15 :

When a using-declaration brings names from a base class into a derived class scope, member functions and member function templates in the derived class override and/or hide member functions and member function templates with the same name, parameter-type-list (8.3.5), cv-qualification, and ref-qualifier (if any) in a base class (rather than conflicting). [ Note: For using-declarations that name a constructor, see 12.9. — end note ]

再次没有关于 using 声明之间冲突的文本,但类似于前面案例中的注释,具有两个可能指定冲突函数的 using 声明不是格式错误的,因为没有文本不允许这些声明共存.与前面的情况一样:如果对于函数调用,重载决策选择了这两个函数,则调用是格式错误的。

在您的示例中,SFINAE 始终会从重载集中消除其中一个可能存在冲突的函数,因此在这两种情况下都不会出现问题。

关于c++ - 具有相同签名的模板不会导致编译器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15148087/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com