2017-01-19 9 views
4

Если я дамстанд :: result_of применяется к константному перегруженным методам

typedef std::vector<int> v; 

Тогда ниже, может быть использована для захвата типа постоянного итератора (альтернатива заключается в использовании v::const_iterator, но это зависит от const_iterator тип элемент выполнен явно определен в классе.

typedef typename std::result_of<decltype(&v::cbegin)(v*)>::type const_iterator; 

Действительно, мы можем проверить, что выше делает так, как мы хотим.

static_assert(std::is_same<const_iterator, typename v::const_iterator>::value); 

Однако я обнаружил ошибку компилятора ниже.

typedef typename std::result_of<decltype(&v::begin)(v*)>::type iterator; 

Компилятор жалуется, что метод перегружен (по константному модификатору) и не может быть однозначно решен. Однако я не могу найти синтаксис для устранения двусмысленности. Как минимум, мы ожидаем, что ниже будет однозначно, потому что только версия const может работать на const-объекте. Однако даже нижеследующее аналогично проблематично.

typedef typename std::result_of<decltype(&v::begin)(const v*)>::type const_iterator2; 

Как я могу ссылаться на конкретную версию const или nonconst для начала?

ответ

4

Следующая делает то, что вы хотите:

using v = std::vector<int>; 
using iter = decltype(std::declval<v>().begin()); 
static_assert(std::is_same<iter, typename v::iterator>::value); 

Проблема здесь в том, что &v::begin неоднозначно. Есть две функции v::begin, а оператор & не имеет возможности узнать, какой из них должен вернуть адрес. Используя это std::declval. Поскольку тип возврата std::declval<v>() равен v, компилятор знает, что вас интересует неконстантный v::begin().

Аналогично, следующий получает вас константные версии:

using citer = decltype(std::declval<const v>().begin()); 
static_assert(std::is_same<citer, typename v::contst_iterator>::value); 

Обратите внимание, что никакие объекты не создаются в этом коде. std::declval не имеет определения, поэтому он работает только в неоцененных контекстах, таких как decltype.

+0

Я понимаю этот ответ, но почему модификатор 'const' аргумента' v * 'выше не устраняет двусмысленность? – epl

+0

Тип возврата 'std :: declval ()' не 'v'. – skypjack

+0

@epl, потому что '&' уже пробовал и не смог принять адрес неоднозначного имени функции до того, как параметры когда-либо были просмотрены. –