当前位置: 首页 > 知识库问答 >
问题:

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

乐正玺
2023-03-14

尝试获取两个回调的签名并生成一个回调签名,该回调签名使用它们的每个返回值。

给定回调AB=

例1)A:int(char)B:double(bool)=

例2)A:void(char)B:void(int)=

实例化以val为参数的回调时遇到奇怪的编译器错误:

错误:无效的参数类型'val'

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;
}

虽然使用void实例化my\u func没有问题,但my\u fwd(4)(5)失败,我想了解原因。

我已经找到了一个解决方法,专门针对Ret==void(无效)使用my\u fwd(我的fwd):

// 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;
};

试图在内部实例化的编译器之间有什么区别

<代码>my\u fwd

-

main()中的手动版本:my\u func

val专业化是修复的正确方法吗?替代方案?我显然对专业化和代码复制不感兴趣。


共有1个答案

呼延明朗
2023-03-14

将void作为模板参数进行安装与手动写入void(void)之间的区别在于,后者不会生成采用void参数的函数。将(void)列为函数的参数是一种语法结构,其含义与()相同。它是C语言的遗留版本,其中表示“参数未指定”,而表示“无参数”C删除了未指定的大小写,此处的“无参数”表示“无参数”。

但是,模板实例化发生在语法处理之后很长时间,因此实际上尝试使用T=val实例化函数的参数(T)会导致错误。就像尝试声明采用(std::remove_reference的函数一样

恐怕你能解决这个问题的唯一方法就是专门研究void。

 类似资料:
  • 受这个答案的启发,我生成了这段代码,其输出取决于编译器: 如果使用 GCC 11 编译,调用

  • 假设有一个模板函数 接受任意数量的参数。给定最后一个参数始终是 ,我如何实现下面显示的 模板,以便 包含此 的参数? 例如,如果像这样调用,应该是: 我的第一个想法是: 但这不会编译: 问题一: 为什么这不能编译?为什么模板参数演绎失败? 最终,我想出了这个解决方案: 这里,是,即中的最后一种类型。然后,的临时值被传递到,其中。这行得通,但在我看来很难看。 问题二: 我想知道如果没有两个函数和的临

  • 如果我没有理解错的话,类模板定义了一个函数,所以当我调用时,编译器有可能进行隐式强制转换,但是在函数模板的情况下,此时没有函数定义,所以隐式强制转换不会发生。 但我不明白为什么编译器不能创建函数定义,然后应用隐式强制转换? 错误是: 在函数“int main()”中:    25:24:错误:调用“test2::add(void(&)(int))”没有匹配函数    25:24:注:候选人是:  

  • 函数取得的参数是你提供给函数的值,这样函数就可以利用这些值 做 一些事情。这些参数就像变量一样,只不过它们的值是在我们调用函数的时候定义的,而非在函数本身内赋值。 参数在函数定义的圆括号对内指定,用逗号分割。当我们调用函数的时候,我们以同样的方式提供值。注意我们使用过的术语——函数中的参数名称为 形参 而你提供给函数调用的值称为 实参 。 使用函数形参 例7.2 使用函数形参 #!/usr/bin

  • 在下面的代码中,为什么模板函数的显式扩展无法编译,而条形扩展却成功编译?实时链接-https://godbolt.org/z/o8Ea49KEb 请注意,这两个函数的主体中都使用了模板参数T2,唯一的区别是已手动替换条形图的函数参数。 这个问题是在阅读了std::c条件-无效参数类型“无效”后提出的,即使在测试“无效”并试图简化问题时也是如此。

  • 我有这样的情况 这是我自己的Vector类,构造函数模拟了Vector的行为(u可以通过使用interator提供的数据范围来构造它),但增加了一个要求,即容器是与正在构造的容器相同类型的模板。我有错误 5.cpp:16:36:错误:调用“Vector::Vector(Vector::Iterator,Vector::Iterator)”没有匹配函数5.cpp:16:36:注意:候选项是:包含在5