【问题标题】:Why won't this template compile?为什么这个模板不能编译?
【发布时间】:2016-01-22 13:10:06
【问题描述】:

我有以下与 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'    

【问题讨论】:

  • nullptr != NULL。想想吧。
  • 构造函数接受一个func_type,它是一个函数指针,这样nullptr就可以了吗?
  • 我怀疑R(Ts...) 是隐含的R __cdecl (Ts...),所以部分特化不匹配int __stdcall(int)
  • 还要注意 f1 和 f2 可以编译,只有 f3 有问题
  • @T.C.如果是这样,是否有某种方法可以传递调用约定?

标签: c++ templates


【解决方案1】:

在 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.

【讨论】:

    猜你喜欢
    • 2010-11-24
    • 1970-01-01
    • 1970-01-01
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多