假设我有这样的事情:

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(),您无需指定其参数,从而避免了烦人的类型名重新输入。 (ignore_and_throw非常类似于C++ 14 lambda产生的东西)。

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

07-24 09:45
查看更多