2014-09-25 2 views
1

Предположим, у меня есть что-то вроде этого:Dummy аргументы в 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)>); 

там, где нет никакой связи между Foo, Bar и Baz.

Теперь предположим, что я хотел бы передать каждую из этих функций регистра идентичной лямбда, которую игнорирует свой аргумент. Есть ли что-нибудь, что я могу включить в список аргументов лямбды, который означает «что-нибудь здесь, я просто собираюсь выбросить эту вещь»?

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

Если вы создаете структуру, вы можете также прорезать лямбду и просто использовать функтор. –

ответ

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 производит в сторону).

Ваш Anything следует, вероятно, называть sink_and_ignore или ignore_arg, и является приемлемым.

+0

Вы сказали C++ 03, но, вероятно, означали C++ 11, так как вы использовали ссылку rvalue. Однако для игнорируемых аргументов 'const &' должен работать так же хорошо и действительно работает на C++ 03. – Oberon

+1

@oberon yep, я просто набираю 'T &&', когда мне сейчас все равно. :) – Yakk

Смежные вопросы