假设我有这样的事情:
struct Foo {};
struct Bar {};
struct Baz {};
// ...
void RegisterListener1(std::function<void(Foo)>);
void RegisterListener2(std::function<void(Bar)>);
void RegisterListener3(std::function<void(Baz)>);
Foo
,Bar
和Baz
之间没有关系。现在,假设我想为每个这些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_ignore
或ignore_arg
,并且可以接受。