gpt4 book ai didi

c++ - Clang 与 GCC : Error in unevaluated context breaks SFINAE

转载 作者:太空狗 更新时间:2023-10-29 21:37:07 24 4
gpt4 key购买 nike

同时从 my previous question 继续工作,我遇到了 clang 和 GCC 的不同行为。
我需要检查成员函数指针,因为我需要知道该函数是否被继承。

在 SFINAE 上下文中比较成员函数指针时,成员函数 Foo::foo() 存在,但其主体包含代码 (x.hello())最终不编译。

以下代码使用 clang 进行编译。然而,GCC 似乎评估了 Foo::foo() 的函数体并以错误退出(“struct Caller”没有名为“hello”的成员),尽管在未评估的 SFINAE 上下文中(或者我希望如此)。

#include <iostream>
#include <type_traits>

struct Foo
{
template <typename T> void foo(T&& x) { x.hello(); }
};

struct Caller
{
template <typename T>
auto call(T&& x) -> decltype(
std::enable_if_t<
std::is_same<
decltype(&T::template foo<decltype(*this)>),
void (T::*)(decltype(*this))
>::value
>())
{
//x.foo(*this);
}
};

int main()
{
Caller c;
c.call(Foo());
}

我测试了:

  • clang 3.8.0
  • g++ 6.1.0

两者的编译器选项:-std=c++14 -O2 -Wall -pedantic -pthread

live example

我的问题:

  1. 谁是对的? Clang 还是 GCC?
  2. 如何获取代码以使用 GCC 进行编译?

最佳答案

第二个问题的回答

How can I get the code to compile with GCC?

我会简化传递给 decltype() 的表达式。如果 call 方法的编译依赖于 x.foo(*this); 的编译,那么你应该使用它。

struct Foo
{
template <typename T> void foo(T&& x) { x.hello(); }
};

struct Caller
{
template <typename T>
auto call(T&& x, int) -> decltype(x.foo(*this))
{
//x.foo(*this);
}
template <typename T>
void call(T&&, char){ std::cout << "hello" << std::endl;}
};

int main()
{
Caller c;
c.call(Foo(), 0);
}

Demo here.


我认为 OP 与 gcc 的问题在于正在获取函数的地址(如果没有明确获取,则衰减为函数指针)。我认为这是标准中的一个极端案例。如果需要 Foo::foo 方法,则 x.hello() 需要存在(编译);一般来说,获取某物的地址可以满足这一点,但在未评估的上下文中(decltype()),我不确定这是否适用 - 当然 clang 不需要它存在(MSVC 也不需要).

在这方面,

Who is right? Clang or GCC?

我怀疑 clang 实现了对标准的更宽松的阅读,并且可能更正确的阅读。 decltype() 的操作数是未计算的操作数,参见 [dcl.type.simple]/4 ;

The operand of the decltype specifier is an unevaluated operand (Clause [expr]).

关于c++ - Clang 与 GCC : Error in unevaluated context breaks SFINAE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38371924/

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