clang和gcc中的模板转换运算符类型推导不同
templated conversion operator type deduction differs in clang and gcc
在过去的几天里,我一直在与编译器之间在模板化转换运算符类型推导方面的差异作斗争,我终于将其中至少一个差异归结为堆栈溢出大小的示例:
void foo(int i);
struct any_const_reference {
template <typename T>
operator const T&();
};
template <typename T, typename Enable=void>
struct detect_call : std::false_type { };
template <typename T>
struct detect_call<T,
decltype( declval<T>()( any_const_reference() ) )
> : std::true_type { };
演示
表达式detect_call<decltype(foo)>::value
在clang中给出true
,在gcc中给出false
(使用我能找到的任何现代版本的编译器,最新的是gcc 5.2和clang 3.8)。问题:
- 哪个是正确的?也就是说,哪个符合C++标准
- 造成这种差异的原因是什么
- 一般来说,在转换运算符(或这种形式的任何转换运算符,例如
template <typename T> operator T();
)中,应用于T
的类型推导规则是什么?它们在C++标准中的何处给出
注意:这似乎与这个问题类似:转换运算符的模板参数类型推导(事实上,我也遇到了确切的区别),但我不太清楚这个答案和这个例子之间的映射。如果这只是这个问题的另一个实例,那么这个问题可以归结为如何将这个问题映射到这个用例中。
这可以简化为实际调用foo()
:
void foo(int ) { }
struct any_const_reference {
template <typename T>
operator const T&();
};
int main() {
foo(any_const_reference{}); // ok on clang
// error on gcc
}
这是一个gcc错误(根据上面TC的评论,#63217)。根据[temp.dexer.conv],这应该将T
推断为int
,因为引用和限定符都应该被移除(在这种情况下,P
是const T&
,A
是int
)。
相关文章:
- 有没有一种方法可以通过"typedef"为重新定义的基本类型定义特征和强制转换运算符
- JS相等运算符(如===)是否可以使用embind类型
- 为什么在我的函数类型后使用引用运算符 (&) 允许我修改它返回的值?
- 将所有模板类型传递给运算符,而不指定所有类型
- 标准库类型的赋值运算符的引用限定符
- 错误 C2679:二进制"<<":未找到采用类型 'std::string_view' 的右侧操作数的运算符(或者没有可接受的转换)
- 如何确保接受的C++模板类型使运算符重载?
- C2678 二进制 '==':未找到采用 'Card' 类型左操作数的运算符(或者没有可接受的转换)
- C2679 二进制"<<":未找到采用右操作数类型的运算符
- 使用类型id运算符的最佳替代方法
- 为什么 std::make_shared 无法编译带有已删除运算符 new 的类型?
- int* 和 int[] 类型对二进制运算符 + 的操作数无效
- 错误:表达式必须具有算术、无作用域枚举或带有运算符重载的指针类型
- 运算符'<'不能应用于类型 'string' 和 'string' 的操作数
- 为什么重载运算符可以返回其返回类型以外的其他内容?
- 表达式必须具有类类型(运算符)
- 使用许多类型运算符过载时,模棱两可的超载
- 类型转换为类型&&运算符
- 返回类型 ?:运算符和 C++ Primer 中的措辞
- 返回类型与返回类型(运算符++)不相同,也不协变