Будучи не объявленным constexpr
, std::forward
отбрасывает консистентность для любой функции, которой она передает аргументы. Почему std::forward
не объявлено constexpr
само по себе, чтобы оно могло сохранить консистентность?
Пример: (протестировано с g ++ snapshot-2011-02-19)
#include <utility>
template <typename T> constexpr int f(T x) { return -13;}
template <typename T> constexpr int g(T&& x) { return f(std::forward<T>(x));}
int main() {
constexpr int j = f(3.5f);
// next line does not compile:
// error: ‘constexpr int g(T&&) [with T = float]’ is not a constexpr function
constexpr int j2 = g(3.5f);
}
Примечание: технически было бы легко сделать std::forward
constexpr, например, подобным образом (обратите внимание, что в g std::forward
было заменено на fix::forward
):
#include <utility>
namespace fix {
/// constexpr variant of forward, adapted from <utility>:
template<typename Tp>
inline constexpr Tp&&
forward(typename std::remove_reference<Tp>::type& t)
{ return static_cast<Tp&&>(t); }
template<typename Tp>
inline constexpr Tp&&
forward(typename std::remove_reference<Tp>::type&& t)
{
static_assert(!std::is_lvalue_reference<Tp>::value, "template argument"
" substituting Tp is an lvalue reference type");
return static_cast<Tp&&>(t);
}
} // namespace fix
template <typename T> constexpr int f(T x) { return -13;}
template <typename T> constexpr int g(T&& x) { return f(fix::forward<T>(x));}
int main() {
constexpr int j = f(3.5f);
// now compiles fine:
constexpr int j2 = g(3.5f);
}
Мой вопрос: почему std::forward
не определен как fix::forward
?
Примечание 2: этот вопрос в некоторой степени связан с другим моим вопросом о constexpr std :: tuple , поскольку std::forward
не является constexpr
- техническая причина, по которой std::tuple
не может быть создан путем вызова его cstr со значениями, но этот вопрос, очевидно, является (гораздо) более общим.