c++ - 为什么这个模板不能编译?

标签 c++ templates

我将以下类与 MSVC2013 Update 4 一起使用:

template <typename T>
class MyFunction;

template<typename R, class... Ts>
class MyFunction < R(Ts...) >
{
public:
    using func_type = R(*)(Ts...);

    MyFunction(func_type f)
        : m_func(f)
    {
    }

    R operator()(Ts ... args)
    {
        return m_func(args...);
    }

private:
    func_type m_func;
};

如果我这样使用它:

MyFunction<int (int)> f1(nullptr);
MyFunction<int __cdecl(int)> f2(nullptr);
MyFunction<int __stdcall(int)> f3(nullptr);

为什么 f3 编译失败? (考虑到 __cdecl 有效!)。

error C2079: 'f3' uses undefined class 'MyFunction<int (int)>'  
error C2440: 'initializing' : cannot convert from 'nullptr' to 'int'    

最佳答案

在MSVC中,调用约定是函数类型的一部分;默认调用约定是 __cdecl,所以 R(Ts...) 实际上是 R __cdecl (Ts...) 而不是匹配 int __stdcall(int)

如果您使用 /Gz 进行编译,这会生成默认调用约定 __stdcall,您会在 f2 上看到错误。

您必须为您想要支持的所有调用约定编写部分特化:

template<class F, class R, class... Args>
class MyFunctionImpl {
public:
    using func_type = F*;

    MyFunctionImpl(func_type f)
        : m_func(f)
    {
    }

    R operator()(Args ... args)
    {
        return m_func(args...);
    }

private:
    func_type m_func;
};

template<typename R, class... Ts>
class MyFunction < R __cdecl(Ts...) >
    : MyFunctionImpl<R __cdecl(Ts...), R, Ts...> {
    using MyFunctionImpl<R __cdecl(Ts...), R, Ts...>::MyFunctionImpl;
};

template<typename R, class... Ts>
class MyFunction < R __stdcall(Ts...) >
    : MyFunctionImpl<R __stdcall(Ts...), R, Ts...> {
    using MyFunctionImpl<R __stdcall(Ts...), R, Ts...>::MyFunctionImpl;
};

// etc.

关于c++ - 为什么这个模板不能编译?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34947513/

相关文章:

c++ - 以私有(private)类为参数的公共(public)函数

php - 在 WooCommerce 的“我的帐户”>“下载”部分更改列名称

c++ - 如何根据标记的参数包调用一组可 rebase 类构造函数?

c++ - 模板链表类上奇怪的 undefined reference

c++ - std::string_view 的 noexcept 构造函数

c++ - 调试构建编译比发布慢得多

c++ - 使用 -O3 在 GCC 中编译共享库不会导出与 -O0 一样多的符号

c++ - 使用非类型模板参数有什么好处?

c++ - 在 C++ 中,可以在运行时设置/更改类属性 - 公共(public)、私有(private)或 protected 吗?

c++ - 计算一个int在一个文件中出现的次数