Consider an example:
template <void (*Foo)()>
struct S {
};
int main() {
struct A {
static void x() { }
};
S<&A::x> s;
}
The code compiles in clang, gcc argue that x
doesn't have a linkage...
For quite similar example just when using lambda expression:
template <void (*Foo)()>
struct S {
};
int main() {
auto lambda = []{};
S<+lambda> s;
}
Both gcc and clang agree not to compile the code: according to gcc the function returned by unary + doesn't have linkage, clang states in contrast that cast operator to the function isn't declared as constexpr. Are there any reasons to disallow lambda cast to function pointer to be used in constexpr context?
Find below errors produced by compilers and the live demos:
gcc:
prog.cc:7:14: error: 'main()::::_FUN' is not a valid template argument for type 'void (*)()' because 'static constexpr void main()::::_FUN()' has no linkage
clang:
prog.cc:7:8: note: non-constexpr function 'operator void (*)()' cannot be used in a constant expression
constexpr lambda expressions in C++ Visual Studio 2017 version 15.3 and later (available in /std:c++17 mode and later): A lambda expression may be declared as constexpr or used in a constant expression when the initialization of each data member that it captures or introduces is allowed within a constant expression.
A constexpr function is one whose return value is computable at compile time when consuming code requires it. Consuming code requires the return value at compile time to initialize a constexpr variable, or to provide a non-type template argument.
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.
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.
Clang hasn't implemented constexpr
lambdas yet.
GCC is behind in other ways. [temp.arg.nontype]/2's only interesting constraint is that the argument shall be a constant expression. But [expr.const]/(5.2) makes it one, so that's perfectly valid. Perhaps GCC didn't implement N4198 yet, which eliminated the linkage requirement.
Note that both constexpr
lambdas and no-linkage function pointer template arguments are post C++14 features.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With