组合模板参数以形成函数签名时,void参数无效

时间:2014-03-07 12:17:15

标签: c++ templates c++11

尝试获取两个回调的签名并生成使用其每个返回值的回调签名。

给定回调AB =>生成F

Ex 1)A:int(char) B:double(bool) => F:double(int)

Ex 2)A:void(char) B:void(int) => F:无效(无效)

在使用void作为参数实例化回调时遇到奇怪的编译器错误:

error: invalid parameter type ‘void’

有问题的代码

template<class Signature>
struct my_func;

template<class Ret, class... Args>
struct my_func<Ret(Args...)>
{};

template<class FuncA, class FuncB>
struct my_fwd;

template<class ORet, class... OArgs,
         class Ret, class... Args>
struct my_fwd<
  my_func<ORet(OArgs...)>,
  my_func<Ret(Args...)>
  >
{
  my_func< ORet(Ret) > func;  // <--- error
};

int main(int, char *[])
{
  my_func<void(int)> my3;  // (1)
  my_func<void(void)> my4; // (2)
  my_func<void()> my5;     // (3)

  my_fwd< decltype(my3), my_func<void(char)> > fwd1; // (4)
  my_fwd< decltype(my3), decltype(my4) > fwd2;       // (5)

  return 0;
}

虽然使用my_func void(1), (2), (3)进行实例化没有问题,但my_fwd的{​​{1}}失败,我希望了解原因。

解决方法?!

我找到了一种解决方法,专门针对(4) (5) my_fwd进行了解决方法:

Ret == void

问题

尝试在

中实例化的编译器之间有什么区别

// with this specialization i can avoid the error template<class ORet, class... OArgs, class... Args> struct my_fwd< my_func<ORet(OArgs...)>, my_func<void(Args...)> > { my_func< ORet() > func; };

- &GT; my_fwd< my_func<void(int)>, my_func<void(char)> >

main()中的手册版本:my_func<void(void)> func

my_func<void(void)> my4专门化正确方法是否可以修复?备择方案?我显然对专业化和代码重复不感兴趣。

1 个答案:

答案 0 :(得分:4)

使用void作为模板参数进行实例化并手动编写void (void)之间的区别在于后者生成带有void参数的函数。将(void)列为函数的参数是一个语法结构,其含义与()相同。这是来自C的遗产,其中()表示“参数未指定”,(void)表示“无参数”。 C ++删除了未指定的大小写,()表示“没有参数”。

但是,模板实例化在语法处理之后很久就会发生,因此实际尝试使用(T)实例化函数的参数T = void会导致错误。正如尝试声明一个函数(std::remove_reference<decltype(std::declval<void*>())>::type)(即void实际拼写为类型一样)是错误的。

我担心你能解决这个问题的唯一方法就是专注于void