ошибка: `type` в `class std::result_of` не указывает тип

Пример ниже не работает со всеми компиляторами, которые я пробовал: gcc-8.2, clang-8.0 (были опробованы оба варианта --std=c++17 и std=c++2a) и zapcc-2017.08.

С моей точки зрения, пример кода действителен и должен быть скомпилирован. Или, по крайней мере, должна быть более всеобъемлющая ошибка. Это похоже на ошибку в стандартной библиотеке, не покрывающую этот конкретный случай для result_of. Я ошибся?

#include <type_traits>
using namespace std;
struct bar {
    int a;
    long b;
};

template<auto M>
struct foo {
    static auto q(bar & b) {
        return b.*M;
    }
};

template<auto M>
auto qoo(bar & b) {
    return b.*M;
}


// error: 'type' in 'class std::result_of<int(bar&)>' does not name a type
using f = typename result_of<decltype(foo<&bar::a>::q)>::type;
// error: 'type' in 'class std::result_of<int(bar&)>' does not name a type
using q= typename result_of<decltype(qoo<&bar::a>)>::type;

person hutorny    schedule 08.11.2018    source источник
comment
Какие-либо особенности, перечисленные в документе cppreference для result_of, отвечают на ваш вопрос?   -  person Lightness Races in Orbit    schedule 08.11.2018
comment
@ πάνταῥεῖ Вы находитесь в режиме С++ 11, что приводит к сбою по совершенно другим причинам. Поместите его в режим С++ 17, и вы получите тот же результат, что и OP.   -  person Lightness Races in Orbit    schedule 08.11.2018
comment
@LightnessRacesinOrbit К сожалению, да.   -  person πάντα ῥεῖ    schedule 08.11.2018
comment
@Lightness Races in Orbit - ни один из пяти перечисленных там   -  person hutorny    schedule 08.11.2018


Ответы (3)


Попробуйте с

using f = typename std::result_of<decltype(&foo<&bar::a>::q)(bar&)>::type;

using q= typename std::result_of<decltype(&qoo<&bar::a>)(bar&)>::type;

Как лучше объяснил TC, type в std::result_of — это тип, возвращаемый из типа вызываемого объекта при вызове с некоторыми типами аргументов.

Если вы пишете

std::result_of<decltype(foo<&bar::a>::q)>

вы передаете в std::result_of только тип вызываемого (почти: вам также нужен & перед foo); вам также необходимо передать тип аргументов (в данном случае только один аргумент: ссылка bar), поэтому

std::result_of<decltype(&foo<&bar::a>::q)(bar&)>
person max66    schedule 08.11.2018

result_of_t<F(Args...)> означает "результат вызова/вызова F с Args...".

result_of_t<int(bar&)> означает "результат вызова int с bar&". Которого не существует, потому что вы не можете вызвать int с чем угодно.

result_of не "извлекает тип возвращаемого значения из типа функции".

person T.C.    schedule 08.11.2018

По моему опыту, нет ничего, что result_of мог бы сделать, чего не смог бы decltype (или result_of_t< /a>, что поможет упростить ваш код): Как я могу использовать result_of вместо decltype?

Это верно и в этом случае, когда decltype и declval дадут вам более простой результат, чем result_of:

using f = decltype(foo<&bar::a>::q(declval<bar&>()));
using q = decltype(qoo<&bar::a>(declval<bar&>()));

Живой пример

person Jonathan Mee    schedule 08.11.2018
comment
result_of необходим, если вы хотите поддерживать весь диапазон вызываемых объектов. - person T.C.; 10.11.2018
comment
@Т.С. Я не могу вспомнить пример, в котором я не мог бы использовать некоторую комбинацию declval и decltype для достижения, но я хотел бы понять. Должен ли я задать еще один вопрос, или вы могли бы привести простой пример в комментарии? - person Jonathan Mee; 12.11.2018
comment
Полный набор вызываемых объектов включает указатели на члены. - person T.C.; 12.11.2018
comment
@Т.С. Могу ли я вызвать указатель на элемент с помощью declval? Например: ideone.com/25wpKD - person Jonathan Mee; 13.11.2018
comment
Конечно. Теперь попробуйте написать код, который работает для оба указателя на члены, и объекты функции. - person T.C.; 13.11.2018