2013-12-07 5 views
5

Следующая действует в GCC 4.8:Non-constexpr Function в constexpr конструктор действует

class Value { 
    private: 
     static std::vector<float> compile_time_vector; 
     const bool compile_time_bool; 

     static bool f(void) { 
      compile_time_vector.push_back(2.3); 

      return true; 
     } 

    public: 
     template <typename type_t> 
     constexpr Value(const type_t& value): compile_time_bool(f()) {} 
}; 

станд :: вектор не предназначен для работы во время компиляции, поэтому какой именно код этого производящая? Я использовал класс, чтобы убедиться, что он не оптимизирован.

+0

Он также работает с clang 3.3. – razeh

+0

Кажется, что это может быть ошибкой в ​​том, что шаблоны не создаются, пока они не потребуются. Если вы используете класс в 'static_assert()', он терпит неудачу. Я полагаю, вы использовали его в контексте выполнения. Однако я думаю, что он должен был пожаловаться на 'constexpr', потому что этот конструктор никогда не является постоянным выражением. – mpark

+0

@mpark Черт, я действительно надеялся, что могу использовать std :: vector как список объектов времени компиляции ... есть ли что-нибудь, что делает это? – NmdMystery

ответ

5

Это плохо сформировано, но диагностика не требуется. Проблема в том, что f() в constexpr Value(const type_t& value): compile_time_bool(f()) может не отображаться в постоянном выражении для любого аргумента шаблона. Но учтите:

struct A{}; 
struct B{}; 

bool foo(A); 
constexpr bool foo(B) { return {}; } 

template<class T> 
constexpr bool bar(T p) { return foo(p); } 

Здесь constexpr ность bar зависит от аргумента шаблона. Поэтому:

constexpr A a{}; 
constexpr B b{}; 

//constexpr auto ba {bar(a)}; // error 
constexpr auto ba {bar(b)}; // fine 
auto ba2 {bar(a)};    // fine 

Шаблон функции помечаются как constexpr может производить constexpr и нефизических constexpr специализаций, в зависимости от аргументов шаблона.

Это, вероятно, трудно или невозможно проверить, если шаблон функции не constexpr для любого набора аргументов шаблона (в случае ФП, это может быть возможным, чтобы видеть, что, как f() однозначно относится к Value::f). Поэтому диагностика не требуется.


Соответствующий параграф [dcl.constexpr]/6:

Если экземпляр шаблона специализация constexpr функции шаблона или члена функции шаблона класса будет не в состоянии удовлетворить требования, предъявляемые к constexpr или constexpr конструктор, эта специализация не является функцией constexpr или constexpr конструктором. [Примечание: Если функция является функцией-членом, она все равно будет const, как описано ниже. - конец примечания] Если никакая специализация шаблона не будет даст функцию constexpr или constexpr конструктор, программа плохо сформирована; не требуется диагностика.

N.B. объект const будет поднят на C++ 1y, поэтому лучше использовать функции элемента-метки (а не ctors, очевидно) как как constexpr, так и const.


Фактически, программа имеет UB. Но как только вы создаете экземпляр ctor в контексте, который требует постоянного выражения, ваш компилятор должен жаловаться - как и clang ++ 3.4

Оба компилятора, похоже, принимают вашу программу, если вы используете ctor в контексте, где постоянное выражение не требуется. Я бы сказал, что это расширение, но в этом случае так же сложно выпустить предупреждение («расширение используется, непереносимый код»), чтобы диагностировать программу, в первую очередь, плохо сформировалось.

+1

Не разумно ожидать, что компиляторы обнаружат это в целом - определение того, может ли произвольная функция constexpr выражать постоянное выражение, равносильно проблеме остановки. Кроме того, соответствующая формулировка в * [dcl.constexpr] p6 * была [значительно изменена исправлениями C++ 11] (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html # 1358). –

Смежные вопросы