C++ 为什么带有默认赋值参数的函数不被接受为0-arg生成器?

C++ 为什么带有默认赋值参数的函数不被接受为0-arg生成器?,c++,stl,generator,default-arguments,C++,Stl,Generator,Default Arguments,以下代码尝试使用ns::generateInt()作为std::generate_n()的生成器参数: …然后它编译得很好: $ g++ ./main.cpp $ 从编译器的角度来看,这里发生了什么?我的默认参数生成器函数可以用0个参数调用,所以为什么它不能用作std::generate\n()的生成器参数?仅仅因为generateInt()具有默认参数值不会更改其具有参数的事实,您可以在错误消息中看到: \u生成器=int(*)(int) 默认参数值不是函数类型的一部分。 当您直接调用gen

以下代码尝试使用
ns::generateInt()
作为
std::generate_n()
生成器
参数:

…然后它编译得很好:

$ g++ ./main.cpp
$

从编译器的角度来看,这里发生了什么?我的默认参数生成器函数可以用0个参数调用,所以为什么它不能用作
std::generate\n()
生成器
参数?仅仅因为
generateInt()
具有默认参数值不会更改其具有参数的事实,您可以在错误消息中看到:

\u生成器=int(*)(int)

默认参数值不是函数类型的一部分。

当您直接调用
generateInt()
时,编译器知道
generateInt()
的完整声明,因此它知道它可以允许您忽略默认参数值

但是,在
std::generate_n()
内部,编译器不知道
\u gen生成器
输入参数指向您的
generateInt()
函数。它只知道
\uu gen
指向某个函数,该函数的类型采用
int
参数,默认值的任何知识都将丢失。由于
std::generate\u n()
在调用
\uu gen()
时没有提供该参数值,因此会出现编译器错误

std::generate\u n()
Generator
模板参数需要不带参数的类型。因此,使用1参数
generateInt()
的唯一方法是将其包装在0参数lambda或functor中,例如:

std::generate\u n(std::back\u inserter(v),
5.
[]返回ns::generateInt(/*0*/);};
struct genInt
{
int运算符(){return ns::generateInt(/*0*/);}
};
标准::生成插入器(标准::返回插入器(v),
5.
genInt());
来自以下参考:

g-将被调用的生成器函数对象。 函数的签名应等同于以下内容:

Ret-fun()

注意,它说签名必须是
retfun(),而不是该参数可使用0个参数调用

您可以很容易地将调用包装在lambda中,这样就不会在
ns
中更改代码:

std::generate_n(std::back_inserter(v),
                5,
                [] { return ns::generateInt(); }); 

默认参数不会改变函数的签名。签名仍然包含具有默认值的参数类型。当一个函数接受一个指向另一个不需要参数的函数的指针的参数,但该参数被赋予一个指向一个接受参数的函数的指针(带或不带默认值),那么您就有了类型不匹配。

很好地指出了函数指针作为应用此规则的示例!
  int generateInt( /*int offset = 0*/ )
  {
    return /*offset +*/ rand() % 128;
  }
$ g++ ./main.cpp
$
std::generate_n(std::back_inserter(v),
                5,
                [] { return ns::generateInt(); });