尝试获取两个回调的签名并生成使用其每个返回值的回调签名。
给定回调A
和B
=>生成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
专门化正确方法是否可以修复?备择方案?我显然对专业化和代码重复不感兴趣。
答案 0 :(得分:4)
使用void
作为模板参数进行实例化并手动编写void (void)
之间的区别在于后者不生成带有void
参数的函数。将(void)
列为函数的参数是一个语法结构,其含义与()
相同。这是来自C的遗产,其中()
表示“参数未指定”,(void)
表示“无参数”。 C ++删除了未指定的大小写,()
表示“没有参数”。
但是,模板实例化在语法处理之后很久就会发生,因此实际尝试使用(T)
实例化函数的参数T = void
会导致错误。正如尝试声明一个函数(std::remove_reference<decltype(std::declval<void*>())>::type)
(即void
实际拼写为类型一样)是错误的。
我担心你能解决这个问题的唯一方法就是专注于void
。