2014-09-25 45 views
1

假設我有這樣的事情:lambdas中的虛擬參數將匹配任何類型?

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之間沒有任何關係。

現在,假設我想通過這些寄存器函數的每一個相同的lambda,忽略其參數。有什麼我可以放在lambda的參數列表中,意思是「在這裏匹配任何東西;我只是要拋出這個東西」?

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

我可以用一個函數模板,而不是一個拉姆達的和做這樣的事情:

template<typename T> 
void listener(T) 
{ 
    throw UnsupportedOperationException(); 
} 

// ... 

RegisterListener1(listener<Foo>); 
RegisterListener2(listener<Bar>); 
RegisterListener3(listener<Baz>); 

但這是乏味的,特別是如果仿函數參數的三個註冊函數模板本身,從而有沒有簡單的方法來寫出「內部」參數類型。下面是發生在我在打字的過程中另一個想法:

struct Anything 
{ 
    template<typename T> Anything(const T&) {} 
}; 

// ... 

auto listener = [](Anything) { throw UnsupportedOperationException(); }; 
RegisterListener1(listener); 
RegisterListener2(listener); 
RegisterListener3(listener); 

我與實際好吧,也許我不需要問這個問題了,但有一個更美好選項?

+0

如果你正在創建一個結構,你可能會拋開lambda,只是使用一個仿函數。 – 2014-09-25 14:52:54

回答

5

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

在C++ 03,您可以:

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

,並通過ignore_and_throw()爲您的聽衆。這個函數對象有一個templateoperator(),你不必指定參數,爲你節省惱人的類型名稱重新類型。 (ignore_and_throw與C++ 14 lambda產生的效果非常相似)。

您的Anything應該可能被稱爲sink_and_ignoreignore_arg,並且是可以接受的。

+0

您說過C++ 03,但可能意味着C++ 11,因爲您使用了右值引用。然而,對於被忽略的參數'const&'應該工作得很好,並且真正在C++ 03中有效。 – Oberon 2014-09-25 14:58:41

+1

@oberon是的,現在我不在乎自動輸入'T &&'。 :) – Yakk 2014-09-25 15:02:14