c++ - 当我更改类型参数名称时,模板替换失败 - 编译器错误?

标签 c++ visual-studio templates template-meta-programming compiler-bug

以下大部分代码取自 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 {};

突然,打印出falseis_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/

相关文章:

C#模板参数作为模板接口(interface)

c++ - 如何确保一次只有一个进程访问共享内存

c++ - 如何在静态函数中使用成员函数数组?

c++ - 使用 Visual Studio C++ 找到的文件大小不正确

visual-studio - 在立即窗口Visual Studio中调用异步方法

c# - 不可访问的内部资源文件?

c++ - 你能静态地断言对象可以转换为某种类型吗?

C++ 编译时多态性

c++ - 当您将文字常量分配给右值引用时会发生什么?

c++ - 如何为多线程应用程序制作全局对象