Вызов constexpr в аргументе шаблона по умолчанию

154
16

В С++ 11 я использую функцию constexpr как значение по умолчанию для параметра шаблона - это выглядит так:


template <int value>
struct bar
{
static constexpr int get()
{
return value;
}
};

template <typename A, int value = A::get()>
struct foo
{
};

int main()
{
typedef foo<bar<0>> type;

return 0;
}


g++ 4.5 и 4.7 компилирует это, но Clang++ 3.1 этого не делает. Сообщение об ошибке от clang:


clang_test.cpp:10:35: error: non-type template argument is not a constant expression
template <typename A, int value = A::get()>
^~~~~~~~
clang_test.cpp:17:19: note: while checking a default template argument used here
typedef foo<bar<3>> type;
~~~~~~~~~^~
clang_test.cpp:10:35: note: undefined function 'get' cannot be used in a constant expression
template <typename A, int value = A::get()>
^
clang_test.cpp:4:23: note: declared here
static constexpr int get()
^
1 error generated.

Какой из них правильный?

спросил(а) 2012-05-23T16:36:00+04:00 8 лет, 9 месяцев назад
1
Решение
153

Ричард Смит (zygoloid) на канале IRC LLVM коротко поговорил со мной об этой проблеме, которая является вашим ответом


<litb> hello folks
<litb> zygoloid, what should happen in this case?
<litb> http://stackoverflow.com/questions/10721130/calling-constexpr-in-default-template-argument
<litb> it seems to be clang behavior is surprising
<litb> zygoloid, i cannot apply the "point of instantiation" rule to constexpr
function templates. if i call such a function template, the called definition
POI often is *after* the specialization reference, which means at the point of
the call, the constexpr function template specialization is "undefined".
<zygoloid> it a horrible mess. Clang does not do what the standard intends, but
as you note, the actual spec is gloriously unclear
<d0k> :(
<zygoloid> we should instantiate bar<3>::get(), because it is odr-used, but we
don't, because we incorrectly believe it used in an unevaluated context
<zygoloid> conversely, the point of instantiation is too late :/
<zygoloid> PR11851

Поэтому кажется, что иногда Clang создает экземпляр шаблонов функций или функцию-член шаблонов классов, но их создание слишком поздно для вызова, и в других случаях он даже не создает их, потому что он считает, что он никогда не понадобится их (неоценимый контекст).

ответил(а) 2012-05-23T23:56:00+04:00 8 лет, 9 месяцев назад
85

Я думаю, что GCC Clang правильный


цитируется из n3290:


14.3.2 Шаблон аргументов non-type [temp.arg.nontype]

    Аргумент шаблона для непигового шаблона-шаблона без шаблона должен быть одним из следующих:  
        для нетипового шаблона-параметра интегрального или перечисляемого типа, преобразованного выражения константы (5.19) типа шаблона-параметра; или   ...  

ИЗМЕНИТЬ: 5.19 3


Литеральное постоянное выражение является выражением константы основного значения prvalue тип литерала, но не тип указателя. Интегральное постоянное выражение литеральное постоянное выражение интегрального или нелитерационного перечисления тип. [Примечание: такие выражения могут использоваться как границы массива (8.3.4, 5.3.4), в качестве длины битового поля (9.6), в качестве инициализаторов перечислителя, если базовый тип не является фиксированным (7.2), как константы нулевого указателя (4.10), и как выравнивания (7.6.2). -end note] Преобразованное константное выражение типа T является литеральным постоянным выражением, неявно преобразованным в тип T, где неявное преобразование (если оно есть) разрешено в литеральное постоянное выражение и неявная последовательность преобразования содержит только пользовательские преобразования, преобразования lvalue-to-rvalue (4.1), интегральные продвижения (4.5) и интегральные преобразования (4.7) чем сужение конверсий (8.5.4).

[Примечание: такие выражения могут использоваться как выражения case (6.4.2), как инициализаторы перечисления, если базовый тип является фиксированным (7.2), и как интегральные или перечисляемые аргументы шаблона непигового типа (14.3). -end note]


ответил(а) 2012-05-23T16:51:00+04:00 8 лет, 9 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема