以下大部分代码取自 answer作者:彼得·斯科特尼基我正在对其进行试验,并发现了我认为是 MSVC 14.0 Update 3 中的一个错误。
考虑以下代码:
#include <iostream>
template <typename T>
struct identity { using type = T; };
template <typename...>
using void_t = void;
template <typename F>
struct call_operator;
template <typename C, typename R, typename... A>
struct call_operator<R(C::*)(A...)> : identity<R(A...)> {};
template <typename C, typename R, typename... A>
struct call_operator<R(C::*)(A...) const> : identity<R(A...)> {};
template <typename F>
using call_operator_t = typename call_operator<F>::type;
template <typename, typename = void_t<>>
struct is_convertible_to_function
: std::false_type {};
template <typename L>
struct is_convertible_to_function<L, void_t<decltype(&L::operator())>>
: std::is_assignable<call_operator_t<decltype(&L::operator())>*&, L> {};
template <typename, typename = void_t<>>
struct is_callable_object
: std::false_type {};
template <typename L>
struct is_callable_object<L, void_t<decltype(&L::operator())>>
: std::true_type {};
int main()
{
auto x = []() {};
std::cout << std::boolalpha << is_callable_object<decltype(x)>::value;
std::getchar();
}
这会按预期打印 true
,因为编译器生成的 lambda 对象确实实现了 operator()
。
现在让我们将 is_callable_object
中的类型参数名称从 L
更改为 T
(任何与 is_convertible_to_function 中使用的类型名称不同的名称)
导致这个问题,据我所知)。
template <typename, typename = void_t<>>
struct is_callable_object
: std::false_type {};
template <typename T>
struct is_callable_object<T, void_t<decltype(&T::operator())>>
: std::true_type {};
突然,打印出false
。 is_convertible_to_funtion
应该不重要,因为 is_callable_object
不以任何方式依赖它;事实上,如果我删除 is_convertible_to_function
,这个问题就会消失 - 我可以使用我想要的任何类型名称。
正如我所说,我怀疑这是一个错误,所以我问这个问题是为了确保这不是 C++ 标准中的一些奇怪行为;解决这个问题的方法非常简单。
最佳答案
表达式 sfinae 在 msvc 2015 中不起作用。任何它起作用的情况都是偶然的,不要相信它。 decltype
不能可靠地用于在 msvc 2015 中引起 sfinae。
停下来,走开,寻找另一个解决方案。也许尝试编译器内在函数。
不要假设参数名称匹配时的意外工作意味着其他任何东西都会工作,或者它会在稍微不同的程序中工作。
您的解决方法不可信。
关于c++ - 当我更改类型参数名称时,模板替换失败 - 编译器错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38984780/