`typename std::remove_reference<T>` 和 `constexpr typename std::remove_reference<T>` 有什么区别?

What are the differences between `typename std::remove_reference<T>` and `constexpr typename std::remove_reference<T>`?

根据文档(https://en.cppreference.com/w/cpp/utility/move),std::move<T>有两种构造函数,如下所示。

这些构造器有什么区别? 最让我困惑的是为什么第二个构造函数中需要关键字(typename)。

我是 C++ 的新手。对于这个问题的任何提示,我将不胜感激。

template< class T >
typename std::remove_reference<T>::type&& move( T&& t ) noexcept; (since C++11)(until C++14)

template< class T >
constexpr typename std::remove_reference<T>::type&& move( T&& t ) noexcept;  (since C++14)

[...] there are two kinds of constructors for std::move<T>...

不,它们不是构造函数,而是 std::move 的函数签名。一个在 (i.e. since ) 之前,第二个在 C++14 之后。

第二个specifier constexpr is used,意思是

constexpr - specifies that the value of a variable or function can appear in constant expressions

在此处阅读更多内容:What are 'constexpr' useful for?


What confused me most is that why there needs the keyword(typename) in the second constructor.

根据 cppreference.com, there is a helper type for std::remove_reference, since

template< class T >
using remove_reference_t = typename remove_reference<T>::type;  (since C++14)

因此在第二个中,它可能是

template< class T >
constexpr std::remove_reference_t<T>&& move( T&& t ) noexcept;
//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^