I read a trick somewhere how to convert a constant literal value to a static variable (this can be useful in a template). Check out the makeStatic
function in my example code which does this.
I tried to use the result of makeStatic
to another call to makeStatic
:
template <auto VALUE>
consteval const auto &makeStatic() {
return VALUE;
}
struct Foo {
};
struct Bar {
const Foo *x;
};
Foo foo;
int main() {
constexpr Bar bar{&makeStatic<Foo{}>()};
// constexpr Bar bar{&foo};
makeStatic<bar>();
}
This example is compiled by clang and MSVC, but gcc rejects it (godbolt):
<source>: In function 'int main()':
<source>:19:20: error: no matching function for call to 'makeStatic<bar>()'
19 | makeStatic<bar>();
| ~~~~~~~~~~~~~~~^~
<source>:2:23: note: candidate: 'template<auto VALUE> consteval const auto& makeStatic()'
2 | consteval const auto &makeStatic() {
| ^~~~~~~~~~
<source>:2:23: note: template argument deduction/substitution failed:
<source>:19:20: error: the address of 'Foo()' is not a valid template argument
19 | makeStatic<bar>();
| ~~~~~~~~~~~~~~~^~
Which compiler is correct?
Note: if you use the other bar
definition, which uses a global variable to initialize bar
, then gcc compiles the code.
Update: I found a similar bug report in gcc's bugzilla, so it seems this is a gcc bug. I'm still wondering where the standard guarantees that my code is well-formed.