gpt4 book ai didi

带有 enable_if : different behaviour with g++ and clang 的 C++ 模板重载

转载 作者:IT老高 更新时间:2023-10-28 22:41:44 25 4
gpt4 key购买 nike

在解决基类的模板化成员函数的重载时,我观察到 g++ (5.2.1-23) 和 clang (3.8.0) 之间的不同行为,-std=c++14 .

#include <iostream>
#include <type_traits>

struct Base
{
template <typename T>
auto a(T t) -> void {
std::cout<< "False\n";
}
};

template <bool Bool>
struct Derived : public Base
{

using Base::a;
template <typename T, bool B = Bool>
auto a(T t) -> std::enable_if_t<B, void>
{
std::cout<< "True\n";
}
};

int main()
{
Derived<true> d;
d.a(1); // fails with g++, prints "true" with clang
Derived<false> d2;
d2.a(1); // fails with clang++, prints "false" with g++
}

调用Derived<true>::a g++ 失败并显示以下消息:

test.cc: In function ‘int main()’:
test.cc:28:8: error: call of overloaded ‘a(int)’ is ambiguous
d.a(1);
^
test.cc:18:8: note: candidate: std::enable_if_t<B, void> Derived<Bool>::a(T) [with T = int; bool B = true; bool Bool = true; std::enable_if_t<B, void> = void]
auto a(T t) -> std::enable_if_t<B, void>
^
test.cc:7:8: note: candidate: void Base::a(T) [with T = int]
auto a(T t) -> void {
^

以及调用 Derived<false>::a使用 clang++ 失败并显示以下消息:

test.cc:32:6: error: no matching member function for call to 'a'
d2.a(1);
~~~^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/type_traits:2388:44: note: candidate template ignored: disabled by 'enable_if' [with T = int, B = false]
using enable_if_t = typename enable_if<_Cond, _Tp>::type;
^

我的猜测是他们对 using Base::a; 的解释不同。 ,并且在clang中不考虑它,而在g++中(可能太多)考虑了它。我认为会发生的是,如果 Derivedtrue作为参数,然后调用a()被派往Derived的实现,而如果参数是 false , 调用被发送到 Base::a .

他们都错了吗?谁是对的?我应该向谁提交错误报告?有人可以解释发生了什么吗?

谢谢

最佳答案

来自 3.3.10/p3 名称隐藏 [basic.scope.hiding]:

In a member function definition, the declaration of a name at block scope hides the declaration of a member of the class with the same name; see 3.3.7. The declaration of a member in a derived class (Clause 10) hides the declaration of a member of a base class of the same name; see 10.2

还有 7.3.3/p15 使用声明 [namespace.udecl]:

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 ] [Example:

struct B {
virtual void f(int);
virtual void f(char);
void g(int);
void h(int);
};
struct D : B {
using B::f;
void f(int); // OK: D::f(int) overrides B::f(int);
using B::g;
void g(char); // OK
using B::h;
void h(int); // OK: D::h(int) hides B::h(int)
};
void k(D* p)
{
p->f(1); // calls D::f(int)
p->f(’a’); // calls B::f(char)
p->g(1); // calls B::g(int)
p->g(’a’); // calls D::g(char)
}

— end example ]

这是在成员名称查找过程中解决的。因此,它在模板参数推导之前。因此,正如评论中正确提到的那样,无论 SFINAE 判决如何,基本模板功能都是隐藏的。

因此 CLANG 是正确的,而 GCC 是错误的。

关于带有 enable_if : different behaviour with g++ and clang 的 C++ 模板重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34158902/

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