Почему std::forward отбрасывает constexpr-ness?

Будучи не объявленным constexpr, std::forward отбрасывает constexpr-ness для любой функции, в которую он пересылает аргументы. Почему std::forward не объявлено constexpr само по себе, чтобы сохранить constexpr-ness?

Пример: (проверено с помощью моментального снимка g++-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 с rvalues, но этот вопрос здесь, очевидно, (гораздо) более общий.


person Lars    schedule 23.02.2011    source источник
comment
примечание: идентификаторы, начинающиеся с _[A-Z], зарезервированы для разработчиков компилятора. Ваша программа, как таковая, плохо сформирована.   -  person Matthieu M.    schedule 24.02.2011
comment
И _T особенно противен, если вы когда-нибудь перейдете на Windows, где это макрос...   -  person Bo Persson    schedule 24.02.2011
comment
@Matthieu M, @Bo Persson Спасибо. Я заменил все имена _T на T и т. д., чтобы другие могли попробовать код более безопасно/легко.   -  person Lars    schedule 25.02.2011


Ответы (1)


Общий ответ заключается в том, что Рабочая группа по библиотеке комитета C++ не провела исчерпывающего анализа рабочего проекта в поисках возможностей для использования новых основных возможностей. Эти функции использовались там, где у людей было время и желание рассмотреть возможные варианты использования, но не было времени на исчерпывающую проверку.

Есть несколько документов, касающихся дополнительного использования constexpr в работах, например, в рассылка за ноябрь 2010 г..

person Anthony Williams    schedule 23.02.2011
comment
Спасибо. Я знал соответствующий документ N3231. уже, но в нем не упоминается раздел 20.3.3 о std::forward. -- То, что вы приводите, является скорее социальной причиной. Меня интересует концептуальная причина, т. е. есть ли что-то неправильное в создании std::forward constexpr или все будет хорошо? - person Lars; 24.02.2011
comment
Я не вижу причин, почему бы и нет, на первый взгляд. - person Anthony Williams; 24.02.2011
comment
С отчетами о проблемах, позволяющими передавать и вызывать указатели функций в функциях constexpr (и литеральные типы объектов функций уже могут быть constexpr), наличие std::forward не-constexpr кажется неудачным. - person Johannes Schaub - litb; 26.02.2011
comment
N3305 предлагает добавить constexpr для std::forward - person Dave Abrahams; 12.09.2012