tr1 :: mem_fn и члены с аргументами по умолчанию - PullRequest
4 голосов
/ 16 ноября 2008

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

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

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

Class object;

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

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

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

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

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]

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

Ответы [ 2 ]

5 голосов
/ 16 ноября 2008

Функции по умолчанию связаны во время вызова, но не могут быть явно связаны с какой-либо оболочкой из-за способа их реализации. Когда вы передаете &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 голосов
/ 16 ноября 2008

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

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

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

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

Редактировать : у coppro есть более удачное решение для предоставления контекста: std::tr1::mem_fn<void()>(&Class::member)

...