在C使用“无效”模板参数++(Using 'void' template argum

2019-07-03 19:15发布

看看下面的小例子:

using Type1 = std::function<void(void)>;

template <typename T>
using Type2 = std::function<void(T)>;

Type1 whyDoesThisWork;
Type2<void> andYetThisDoesNot;

如果第二类型的别名,我得到的错误“之争可能没有‘无效’类型”。 (I和Xcode 4.5,锵/ C ++ 11 /的libc ++,OS X 10.7测试。)

我觉得这是好奇:我本来期望Type1Type2<void>来表现相同。 这里发生了什么? 并且是有办法来重写所述第二类型的别名,所以我可以Type2<void>和得到std::function<void(void)>代替错误?

编辑我也许应该补充一点,我想这样做的原因是为了允许类似如下:

template <typename ... T>
using Continuation = std::function<void(T...)>;

auto someFunc = []() -> void {
  printf("I'm returning void!\n");
};

Continuation<decltype(someFunc())> c;

Continuation<decltype(someFunc())>变得Continuation<void>和我得到的错误。

Answer 1:

简短的回答是“模板不是字符串替换”。 void f(void)具有意义仅限制,只要它是用于一个别名void f() C ++中,在为了与C.向后兼容

第一步是使用variadics,如在别处指出的。

第二步是搞清楚如何映射void返回功能......好吧,也许是这样std::function<void()> ,或也许别的东西。 我说,也许别的东西,因为不像其他的情况下,你不能调用std::function<void()> foo; foo( []()->void {} ); std::function<void()> foo; foo( []()->void {} ); - 这是不是一个真正的延续。

事情是这样的,也许:

template<typename T>
struct Continuation
{
  typedef std::function<void(T)> type;
};

template<>
struct Continuation<void>
{
  typedef std::function<void()> type;
};

然后用它是这样的:

auto someFunc = []()->void {};
Continuation<decltype(someFunc())>::type c;

它给你你想要的类型。 你甚至可以添加在申请延续:

template<typename T>
struct Continuation
{
  typedef std::function<void(T)> type;

  template<typename func, typename... Args>
  static void Apply( type const& cont, func&& f, Args... args)
  {
    cont( f(args...) );
  }
};

template<>
struct Continuation<void>
{
  typedef std::function<void()> type;
  template<typename func, typename... Args>
  static void Apply( type const& cont, func&& f, Args... args)
  {
    f(args...);
    cont();
  }
};

它可以让你申请的延续到一个功能的执行均匀地如果输入类型是无效,或者如果它是一个非空隙型。

不过,我会问:“你为什么要这么做?”



Answer 2:

我没有一个实际的答案,只有我在评论说:你不能有void作为函数类型,如:

int foo(int, char, void, bool, void, void);     // nonsense!

我相信, T(void)只允许作为对C兼容性符号(其中区分声明原型 ,从C ++非常不同,并需要能够说“不争论”)。

因此,解决方案应该是可变参数:

template <typename ...Args> using myType = std::function<void(Args...)>;

这样,你可以适当地没有参数

myType<> f = []() { std::cout << "Boo\n"; }


Answer 3:

几个答案已经解释的理由。 可添加到这些答案,说明书说(C ++ 11§8.3.5[dcl.func] / 4):

由非依赖型的一个单一的未命名参数的参数列表void相当于空参数列表。 除了这种特殊情况下,参数不得有型品种 void

Type2实施例中, Tvoid(T)是一个依赖型 --IT取决于模板参数。



Answer 4:

当一个函数声明采取类型的参数void ,如std::function<void(void)> ,这是真的话,它需要零个参数只是一个愚蠢的方式。 但是你声明类型2的方式是一个std::function与不返回任何内容(空)的签名,但那要花费1个参数。 空隙不是可被用作参数的类型,它仅仅是一个声明没有参数的方式。 因此,它不与2型工作,因为需要可以用来作为一个参数的实际类型。



Answer 5:

虚空可以理解为,如果你把它传递给函数空参数。 您没有使用一个空指针毕竟这样

void func (void)

void func ()


文章来源: Using 'void' template arguments in C++