The compiler doesn't need to know the value of &a
at compile time any more than it needs the value of function addresses.
Think of it like this: the compiler will instantiate your function template with &a
as a parameter and generate "object code" (in whatever format it uses to pass to the linker). The object code will look like (well it won't, but you get the idea):
func f__<funky_mangled_name_to_say_this_is_f_for_&a>__:
reg0 <- /* linker, pls put &std::cout here */
reg1 <- /* hey linker, stuff &a in there ok? */
call std::basic_stream::operator<<(int*) /* linker, fun addr please? */
[...]
If you instantiate f<b&>
, assuming b
is another global static, compiler does the same thing:
func f__<funky_mangled_name_to_say_this_is_f_for_&b>__:
reg0 <- /* linker, pls put &std::cout here */
reg1 <- /* hey linker, stuff &b in there ok? */
call std::basic_stream::operator<<(int*) /* linker, fun addr please? */
[...]
And when your code calls for calling either of those:
fun foo:
call f__<funky_mangled_name_to_say_this_is_f_for_&a>__
call f__<funky_mangled_name_to_say_this_is_f_for_&b>__
Which exact function to call is encoded in the mangled function name.
The generated code doesn't depend on the runtime value of &a
or &b
.
The compiler knows there will be such things at runtime (you told it so), that's all it needs. It'll let the linker fill in the blanks (or yell at you if you failed to deliver on your promise).
For your addition I'm afraid I'm not familiar enough about the constexpr rules, but the two compilers I have tell me that this function will be evaluated at runtime, which, according to them, makes the code non-conforming. (If they're wrong, then the answer above is, at least, incomplete.)
template <int* p, int* pp>
constexpr std::size_t f() {
return (p + 1) == (pp + 7) ? 5 : 10;
}
int main() {
int arr[f<&a, &b>()] = {};
}
clang 3.5 in C++14 standards conforming mode:
$ clang++ -std=c++14 -stdlib=libc++ t.cpp -pedantic
t.cpp:10:10: warning: variable length arrays are a C99 feature [-Wvla-extension]
int arr[f<&a, &b>()];
^
1 warning generated.
GCC g++ 5.1, same mode:
$ g++ -std=c++14 t.cpp -O3 -pedantic
t.cpp: In function 'int main()':
t.cpp:10:22: warning: ISO C++ forbids variable length array 'arr' [-Wvla]
int arr[f<&a, &b>()];