gpt4 book ai didi

c++ - clang 6 和 clang 7 模板转换运算符区别

转载 作者:可可西里 更新时间:2023-11-01 17:58:09 25 4
gpt4 key购买 nike

我有一些代码使用模板转换运算符来查找通过 ADL 找到的函数的返回类型。

简化后的代码如下所示:

#include <type_traits>

template<typename S>
struct probe {
template<typename T, typename U = S, std::enable_if_t<
std::is_same<T&, U>::value &&
!std::is_const<T>::value, int> = 0>
operator T& ();

template<typename T, typename U = S&&, std::enable_if_t<
std::is_same<T&&, U>::value &&
!std::is_const<T>::value, int> = 0>
operator T&& ();

template<typename T, typename U = S, std::enable_if_t<
std::is_same<T const&, U>::value, int> = 0>
operator T const& () const;

template<typename T, typename U = S&&, std::enable_if_t<
std::is_same<T const&&, U>::value, int> = 0>
operator T const&& () const;
};

namespace foo {
struct bar {};

auto find_me(bar const&) -> int { return 0; }
}

int main() {
// That would be inside a template in my code.
find_me(probe<foo::bar>{});
}

在 clang 6 和 GCC 中,以上代码可以编译。但是,在 Clang 7 中,它不再编译!

https://godbolt.org/z/Lfs3UH

如您所见,clang 6 解析了对 probe<foo::bar>::operator foo::bar&&<foo::bar, foo::bar&&, 0>() 的调用但是 clang 7 失败了,因为它试图调用 probe<foo::bar>::operator const foo::bar&&<const foo::bar, foo::bar&&, 0>()

哪个编译器是正确的?标准中的规则是什么?这是一个新的 Clang 错误还是已修复?


我想检查的情况有很多。不只是foo::bar作为参数,但有许多引用类型,例如:

namespace foo {
struct bar {};

auto find_me(bar const&) -> int { return 0; }
auto find_me(bar&&) -> int { return 0; }
auto find_me(bar const&&) -> int { return 0; }
auto find_me(bar&) -> int { return 0; }
}

int main() {
find_me(probe<foo::bar>{});
find_me(probe<foo::bar&>{});
find_me(probe<foo::bar&&>{});
find_me(probe<foo::bar const&>{});
find_me(probe<foo::bar const&&>{});
}

解析到正确的函数调用很重要。

这是所有这些情况的实例,GCC 成功但 clang 失败:https://godbolt.org/z/yrDFMg

最佳答案

这个简化的示例代码说明了 clang 6/7 和 gcc 之间的行为差​​异:

#include <type_traits>

struct S{
template<class T,class=std::enable_if_t<!std::is_const_v<T>>>
operator T& ();
};

void test() {
S a;
const int& i = a; //Accepted by Gcc and clang 6 accept, rejected by clang 7
}

Gcc 和 Clang 6 接受该代码,而 clang 7 拒绝它。

在 Gcc 的情况下,T=intT=const int 都被认为是情况。仅适用于 clang 7 T=const int。因为 T=const int 被禁用,clang 7 拒绝代码。

根据 [over.match.ref] :

The conversion functions of S and its base classes are considered. Those non-explicit conversion functions that are not hidden within S and yield type “lvalue reference to cv2 T2” (when initializing an lvalue reference or an rvalue reference to function) or “cv2 T2” or “rvalue reference to cv2 T2” (when initializing an rvalue reference or an lvalue reference to function), where “cv1 T” is reference-compatible with “cv2 T2”, are candidate functions. For direct-initialization, those explicit conversion functions that are not hidden within S and yield type “lvalue reference to cv2 T2” or “cv2 T2” or “rvalue reference to cv2 T2”, respectively, where T2 is the same type as T or can be converted to type T with a qualification conversion, are also candidate functions.

在我们的例子中,这意味着将 S 转换为 int&const int& 可能是候选。

[temp.deduct.conv] :

Template argument deduction is done by comparing the return type of the conversion function template (call it P) with the type that is required as the result of the conversion (call it A; see [dcl.init], [over.match.conv], and [over.match.ref] for the determination of that type) as described in [temp.deduct.type].

所以我认为两个字面的解读是可以接受的:

  1. gcc认为转换的结果并不代表转换序列的结果,所以它首先根据[over.match.ref] 然后对所有可能的转换序列进行转换算子的模板实参推导。

  2. clang 认为转换的结果确实意味着转换序列的目标。并且它仅对 T=cont int 执行参数推导。

根据我在标准中阅读的内容,我不能说什么是标准的“正确”解释。尽管如此,我认为 clang 行为通常与模板参数推导更一致:

template<class T,class=std::enable_if_t<std::is_const_v<T>>>
void f(T& x);

void test(){
int i;
f(i);
// If considering that the argument type is int caused
// template argument deduction failure, then template argument
// deduction would be performed for a const int argument.
// But template argument deduction succeeds. So T is deduced to int.
// Only after this deduction template argument substitution happens.
// => both gcc and clang reject this code.
}

关于c++ - clang 6 和 clang 7 模板转换运算符区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52652103/

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