Я не понимаю эти применения 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;