c++ - Confusion about pointer values being compile-time constatns -
in c++, possible pointer values compile-time constants. true, otherwise, non-type template parameters , constexpr
won't work pointers. however, far know, addresses of functions , objects of static storage known (at least) @ link-time rather compile-time. following illustration:
main.cpp
#include <iostream> template <int* p> void f() { std::cout << p << '\n'; } extern int a; int main() { f<&a>(); }
a.cpp
int = 0;
i'm wondering how address of a
possibly known when compiling main.cpp
. hope explain little me.
in particular, consider this
template <int* p, int* pp> constexpr std::size_t f() { return (p + 1) == (pp + 7) ? 5 : 10; } int main() { int arr[f<&a, &b>()] = {}; }
how should storage arr
allocated?
plus: mechanism seems rather robust. when enabled randomized base address, correct output obtained.
the compiler doesn't need know value of &a
@ compile time more needs value of function addresses.
think of this: compiler instantiate function template &a
parameter , generate "object code" (in whatever format uses pass linker). object code (well won't, 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 instantiate f<b&>
, assuming b
global static, compiler 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 code calls 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 call encoded in mangled function name. generated code doesn't depend on runtime value of &a
or &b
. compiler knows there such things @ runtime (you told so), that's needs. it'll let linker fill in blanks (or yell @ if failed deliver on promise).
for addition i'm afraid i'm not familiar enough constexpr rules, 2 compilers have tell me function evaluated @ runtime, which, according them, makes code non-conforming. (if they're wrong, answer above is, @ 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 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>()];
Comments
Post a Comment