模板签名解析为gcc拒绝的void(void);这是有效的C ++吗?

时间:2018-10-16 00:41:22

标签: c++

我认为这段代码是有效的C ++。 MSVC同意,但gcc似乎不同意。 MSVC和我错了吗? (或者我应该输入略有不同的内容?)

#include <iostream>
#include <string>
#include <vector>

#include <functional>

template <typename T>
struct S
{
  template <typename R>
  void f(std::function<R(T)> fn)
  {
    auto p = &fn;
    ++p;
  }
  template <typename R>
  void g(std::function<R(void)> fn)
  {
    auto p = &fn;
    ++p;
  }
};

void f()
{
  S<void> s;
  auto p = &s;
  ++p;
}

int main()
{
    f();
}

错误消息:

<source>: In instantiation of 'struct S<void>':

<source>:26:11:   required from here

<source>:11:8: error: invalid parameter type 'void'

   void f(std::function<R(T)> fn)

        ^

<source>:11:8: error: in declaration 'void S<T>::f(std::function<R(T)>)'

Compiler returned: 1
如果我将文字void编写为参数类型,请使用

gcc似乎很好(请参见函数g()的参数)。但是如果我写T然后将T解析为void(请参见函数f()的参数),那是不高兴的。

1 个答案:

答案 0 :(得分:6)

否,您的示例不是有效的C ++。在Standard section [dcl.fct], paragraph 4中找到了允许(void)成为不带参数的函数参数列表的规则:

  

由单个非依赖类型void的未命名参数组成的参数列表等效于空参数列表。除此特殊情况外,参数的类型不得为 cv void

您问题的关键是单词“ non-dependent”,即不依赖于模板参数。该要求可能是这样写的,因为在模板中编写函数声明void func(T);,期望它始终是仅带有一个参数的函数类型,然后发现在某种情况下可能不是

所以:

void f1(void);           // okay - classic style from C

void f2(void nothing);   // error - the phony "void" parameter cannot be named

void f3(const void);     // error - const void is a different type

using VoidType = void;
void f4(VoidType);       // okay - using a non-dependent type alias

template <typename T>
void f5(T);
void (*fptr)(void) = f5<void>; // error - dependent parameter type cannot be void