以下大多数代码均摘自Piotr Skotnicki的回答。我正在对其进行试验,发现我认为是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。
停下来,走开,找到另一个解决方案。也许尝试编译器内在函数。
当参数名称匹配时,不要以为意外工作意味着其他任何事情都可以工作,或者它将在稍有不同的程序中工作。
您的解决方法不能被信任。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句