Lambda中与任何类型匹配的伪参数

Dummy arguments in lambdas that will match any type?

本文关键字:参数 类型 任何 Lambda      更新时间:2023-10-16

假设我有这样的东西:

struct Foo {};
struct Bar {};
struct Baz {};
// ...
void RegisterListener1(std::function<void(Foo)>);
void RegisterListener2(std::function<void(Bar)>);
void RegisterListener3(std::function<void(Baz)>);

其中FooBarBaz之间没有关系。

现在,假设我想给每个Register函数传递一个相同的lambda,会忽略其参数。我能在lambda的参数列表中放些什么吗?意思是"匹配这里的任何东西;我无论如何都要把它扔掉"?

auto listener = []( /* what? */ ) { throw UnsupportedOperationException(); };
RegisterListener1( listener );
RegisterListener2( listener );
RegisterListener3( listener );

我可以使用函数模板而不是lambda,并做如下操作:

template<typename T>
void listener(T)
{
   throw UnsupportedOperationException();
}
// ...
RegisterListener1( listener<Foo> );
RegisterListener2( listener<Bar> );
RegisterListener3( listener<Baz> );

但这很乏味,尤其是如果三个Register函数的函子参数本身是模板化的,因此没有简单的方法写出"内部"参数类型。在打字的过程中,我想到了另一个想法:

struct Anything
{
    template<typename T> Anything(const T&) {}
};
// ...
auto listener = [](Anything) { throw UnsupportedOperationException(); }; 
RegisterListener1( listener );
RegisterListener2( listener );
RegisterListener3( listener );

事实上,我对此很满意,也许我不需要再问这个问题了,但还有更好的选择吗?

在C++14中,您可以[](auto&&){ throw UnsupportedOperationException(); }

在C++03中,您可以:

struct ignore_and_throw {
  template<class T>
  void operator()(T const&) const {
    throw UnsupportedOperationException();
  }
};

并作为听众传递ignore_and_throw()。这个函数对象有一个template operator(),您不必为它指定参数,这样就省去了令人讨厌的类型名称retype。(ignore_and_throw非常类似于C++14 lambda作为旁白产生的内容)。

您的Anything可能应该被称为sink_and_ignoreignore_arg,并且是可以接受的。