Починить std::invoke_result_t

dmitriy@izvolov.ru
dmitriy@izvolov.ru

Суть проблемы:

#include <type_traits>

// Мы знаем, что {Xs...} == {F, Args...}, но не хотим упоминать F явно.
template <typename... Xs>
void f (Xs...)
{
    // Всё работает.
    using good = typename std::invoke_result<Xs...>::type;
    // Ошибка компиляции.
    using bad = std::invoke_result_t<Xs...>; // !
}

struct call
{
    int operator () () const
    {
        return 0;
    }
};

int main()
{
    f(call{});
}

Получается, что псевдоним std::invoke_result_t нарушает "сигнатуру" оригинальной метафункции std::invoke_result, ломая тем самым вполне корректный код.

Думаю, что правильная реализация будет выглядеть так:

// Правильно.
template <typename... Xs>
using invoke_result_t = typename std::invoke_result<Xs...>::type;

А текущая реализация ошибочна:

// Неправильно.
template <typename X, typename... Xs>
using invoke_result_t = typename std::invoke_result<X, Xs...>::type;
2
рейтинг
в разработке
5 комментариев
Олег Фатхиев

Текущая реализация не ошибочна, std::invoke_result_t обязан принимать строго больше 0 параметров. Проблема, видимо, в overload resolution для алиасов, они не умеют принимать variadic pack-и в таком случае. Кажется подобная проблема уже была в gcc, могу ошибаться. Интересно то, что этот код работает в msvc. Нужно разобраться, что об этом говорит стандарт.

Олег Фатхиев
Обновлено 
dmitriy@izvolov.ru

Олег Фатхиев, std::invoke_result_t — это просто псевдоним. Он прокинет аргументы в std::invoke_result, и если их там окажется 0, то вывалится ошибки.

dmitriy@izvolov.ru
yndx-antoshkka

Это уберёт симптом, но не вылечит болезнь. Надо на уровне языка сделать так, чтобы текущая реализация работала. Тогда автоматически исправится множество подобных проблем.

Спрошу у специалистов по ядру языка, что можно с этим сделать на данный момент.

yndx-antoshkka
yndx-antoshkka

Скинули ссылку на проблему: CWG #1430

yndx-antoshkka
dmitriy@izvolov.ru

yndx-antoshkka, я внимательно прочитал ссылку, но не понял, какие оттуда следуют выводы.

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

dmitriy@izvolov.ru
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).
Все предложения