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

B S*_*son 8 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();
}
Run Code Online (Sandbox Code Playgroud)

错误信息:

<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
Run Code Online (Sandbox Code Playgroud)

如果我将文字void作为参数类型(参见函数参数g())编写,gcc似乎没问题.但它是不快乐的,如果我写的T,然后解析Tvoid(见参数功能f()).

asc*_*ler 6

不,您的示例不是有效的C++.允许(void)成为没有参数的函数参数列表的规则可在标准部分[dcl.fct]第4段中找到:

由非依赖类型的单个未命名参数组成的参数列表void等同于空参数列表.除了这种特殊情况,参数不应具有类型cv void.

您的问题的关键是"非依赖"一词,意味着不依赖于模板参数.这个要求可能是这样编写的,因为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
Run Code Online (Sandbox Code Playgroud)