模板化转换运算符类型推导在 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 和铿锵声 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 错误(#63217 per TC's comment above). Per [temp.deduct.conv],这应该将 T
推断为 int
,因为引用和限定符都应该被删除(在这种情况下 P
是const T&
和 A
是 int
).
在过去的几天里,我一直在与编译器之间在模板化转换运算符类型推导方面的差异作斗争,我终于将至少一个差异归结为一个堆栈溢出大小的示例:
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 和铿锵声 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 错误(#63217 per TC's comment above). Per [temp.deduct.conv],这应该将 T
推断为 int
,因为引用和限定符都应该被删除(在这种情况下 P
是const T&
和 A
是 int
).