Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

can a static constexpr variable be used as a template argument

I have the following piece of code which compiles on older gcc, but not on version 6 (works with -std=c++1z). Clang rejects it too, saying the object val doesn't have the right kind of linkage. I don't understand the difference. Isn't a constexpr variable of a pointer type supposed to work more or less transparently? Is there something I'm missing in the syntax that would allow this to work? Or is this violating some portion of the standard?

typedef void(*t_voidfn)();
template <t_voidfn> struct s {};
void fn() {
  static constexpr t_voidfn val = &fn;
  s<val> x;
}

On the other hand this one works.

typedef void(*t_voidfn)();
template <t_voidfn> struct s {};
void fn() {
  s<&fn> x;
}
like image 299
Martin Avatar asked Sep 11 '16 20:09

Martin


People also ask

Are constexpr variables static?

constexpr int a = 2; Static specifies the lifetime of the variable. A static constexpr variable has to be set at compilation, because its lifetime is the the whole program. Without the static keyword, the compiler isn't bound to set the value at compilation, and could decide to set it later.

Is constexpr implicitly static?

constexpr functions are implicitly inline , but not implicitly static .

What is the point of constexpr?

constexpr indicates that the value, or return value, is constant and, where possible, is computed at compile time. A constexpr integral value can be used wherever a const integer is required, such as in template arguments and array declarations.

Can constexpr be modified?

According to the proposal, an object created within a constexpr expression, can now be changed during the evaluation process - until the evaluation process or the object's lifetime ends.


1 Answers

The first snippet is correct in C++17, but not in C++14 and 11.

For C++14, [temp.arg.nontype]/1 says:

A template-argument for a non-type, non-template template-parameter shall be one of:

[...]

  • a constant expression (5.19) that designates the address of a complete object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as & id-expression, where the id-expression is the name of an object or function, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; or
  • a constant expression that evaluates to a null pointer value (4.10); or
  • a constant expression that evaluates to a null member pointer value (4.11); or
  • a pointer to member expressed as described in 5.3.1; or
  • a constant expression of type std::nullptr_t.

(I've included only the bullets that are directly relevant to pointers and pointers to members.)

Basically, the address of the function in your sample has to be expressed strictly as &fn or fn.

C++11 contains essentially the same wording minus a couple of clarifications introduced by defect reports between 11 and 14:

  • DR1570 clarified the bit about complete objects;
  • DR1398 amended by DR1666 added the last bullet.

For C++17, the restrictions have been relaxed as a result of the adoption of paper N4268 (rationale in N4198). The corresponding paragraph (2) now says:

A template-argument for a non-type template-parameter shall be a converted constant expression (5.20) of the type of the template-parameter. For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):

  • a subobject (1.8),
  • a temporary object (12.2),
  • a string literal (2.13.5),
  • the result of a typeid expression (5.2.8), or
  • a predefined __func__ variable (8.4.1).

[ Note: If the template-argument represents a set of overloaded functions (or a pointer or member pointer to such), the matching function is selected from the set (13.4). — end note ]

N4198 contains good explanations for each of those bullets.

like image 185
bogdan Avatar answered Sep 30 '22 04:09

bogdan