2008-11-16 4 views
4

У меня есть класс с функцией-членом, которая принимает аргумент по умолчанию.tr1 :: mem_fn и члены с аргументами по умолчанию

struct Class 
{ 
    void member(int n = 0) 
    {} 
}; 

С помощью станд :: tr1 :: mem_fn я могу вызвать его:

Class object; 

std::tr1::mem_fn(&Class::member)(object,10); 

Это сказало, если я хочу, чтобы вызвать вызываемую элемент на объекте с аргументом по умолчанию, какой правильный синтаксис?

std::tr1::mem_fn(&Class::member)(object); // This does not work 

г ++ жалуется следующее сообщение об ошибке:

test.cc:17: error: no match for call to ‘(std::tr1::_Mem_fn<void (Class::*)(int)>) (Class&)’ 
/usr/include/c++/4.3/tr1_impl/functional:551: note: candidates are: _Res std::tr1::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class&, _ArgTypes ...) const [with _Res = void, _Class = Class, _ArgTypes = int] 
/usr/include/c++/4.3/tr1_impl/functional:556: note:     _Res std::tr1::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class*, _ArgTypes ...) const [with _Res = void, _Class = Class, _ArgTypes = int] 

Тем не менее, у меня такая же проблема, когда класс :: член перегружен члены, которые принимает различные аргументы ...

ответ

5

функция по умолчанию связана во время вызова, но не может быть привязан к какому-либо обертке неявно, из-за того, как они являются реализованы. Когда вы проходите &Class::member, mem_fn видит только void (Class::*)(int) и не может видеть аргумент по умолчанию. Используя tr1::bind, вы можете связать аргумент по умолчанию явным образом: std::tr1::bind(&Class::member, 0) или вы можете использовать его так же, как и вы, mem_fn, но вы не можете обойтись как в одном объекте. Для этого вам придется написать свой собственный класс-оболочку.

Что касается перегрузок, вам нужно будет явно указать аргументы шаблона для mem_fn, поэтому правый указатель функции будет выбран как в mem_fn<void(int)>(&Class::member).

3

причина в том, что любые аргументы по умолчанию не меняют тип функции.

mem_fn не имеет никакого способа знать функция требует только 1 аргумент, или что второй аргумент функций не является обязательным, так как все знания он получает дано ему по типу &Class::member (который остается void(Class::*)(int)). Для этого в качестве второго аргумента требуется целое число.

Если вы хотите, чтобы передать адрес функции члена перегруженной, вы должны бросить на правый член типа указателя функции:

static_cast<void(Class::*)()>(&Class::member) вместо того, чтобы просто &Class::member, поэтому компилятор имеет контекст, чтобы выяснить, какой адрес должен быть принят.

Edit: coppro имеет более хорошее решение, как обеспечить контекст: std::tr1::mem_fn<void()>(&Class::member)

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