Я не понимаю эти применения std::result_of и decltype

В моем проекте Visual Studio у меня было следующее, и он работал нормально:

template <typename T>
void function(T type)
{

    std::result_of<T()>::type myVar = 5; // This compiled fine with Visual Studio, 
but with GCC it shows the following errors:
    //error: dependent-name ‘std::result_of<T()>::type’ is parsed as a non-type, 
    //but instantiation yields a type. note: say ‘typename std::result_of<T()>::type’ if a type is meant
}

int main() {

    auto lambda = []() { return float(); };
    function(lambda);
    return 0;
}

Я просто хочу понять, является ли компилятор настаивающим на том, чтобы я предварял std:: result_of "typename", потому что это может быть неоднозначным, так как std:: result_of может возвращать класс, а затем:: type может быть членом этого учебный класс? Поэтому он настаивает на добавлении typename? Если это так, то почему Visual Studio это позволяет? Это не соответствует?

Кроме того, поскольку я читал, что result_of устарела по сравнению с C++14 или C++17, я хотел попробовать использовать более общий тип decltype, который должен работать в более сложных условиях. Итак, я попробовал:

template <typename T>
void function(T type)
{
decltype(T()) myVar = 5; // Error, use of deleted function‘main()::<lambda()>::<lambda>()’  main.cpp    
}

Итак, я знаю, что у лямбды есть удаленный конструктор по умолчанию и оператор присваивания копии, но в этом случае я действительно думаю, что при передаче лямбды к этой шаблонной функции вызывается конструктор копирования лямбды, который у него есть. Затем, когда я делаю decltype(T()), я предполагаю, что это вызовет его функцию operator(). Я не понимаю, почему это говорит что-то об удаленной функции.

И наконец я попробовал с:

decltype(std::declval<T()>) myVar = 5;

Потому что я думал, что declval можно использовать так, как если бы он создавал поддельный экземпляр любого звонка, который вы делаете, по крайней мере, так мне это объяснили. Это также терпит неудачу с ошибкой:

msgstr "неверная инициализация ссылки типа 'main()::&&' из выражения типа 'int'

1 ответ

Решение

Результат

Во-первых, компилятору GCC требуется ключевое слово typename до std::result_of потому что возвращаемое значение последнего является классом. И вы должны указать ему использовать его тип для объявления новой переменной.

По поводу вашего комментария:

Кроме того, потому что я прочитал, что result_of устарела с C++14 или C++17

std::result_of устарела с C++17 ( см. здесь почему) и заменена недавно введенной std::invoke_result, так что вы можете использовать его, если у вас есть совместимый компилятор.

decltype

поскольку std::result_of объявлен с точки зрения decltype следующим образом:

  template<typename _Signature>
  struct result_of;

  template<typename _Functor, typename... _ArgTypes>
  struct result_of<F(Args...)> {
      typedef decltype( std::declval<F>()(std::declval<Args>()...) ) type;
  };

Вы можете использовать аналогичное определение:

decltype( std::declval<T>()() ) myVar = 5;
Другие вопросы по тегам