Pointer to an externally linked object as a template parameter of a non-python type

As stated in the standard for templates, one of the parameters of a non-type template can be a pointer to an object. For exapmple:

template <int* x>
void f()
{}

      

However, when an argument is provided during instantiation, only pointers to externally linked objects are allowed. What for? Why doesn't the Standard allow you to instantiate a template without a type with a pointer to an internally linked object?

I've found some explanations in other StackOverflow threads, but it's not clear to me:

The typeless template argument provided in the template argument list is an expression whose value can be determined at compile time. Such arguments must be: constant expressions, addresses of functions or objects with external links, or addresses of static class members.

So if I have static const int x = 10;

in the global scope, is this the address of this object determined at compile time?

Also I found an explanation in the comments:

You don't know what the call stack looks like at compile time. Before your function, you could have named 10 others, or 3 others, or like many others, so the address on the stack where the string is created can change from call to call. When you have an externally linked object, its address is fixed at compile / binding time.

How can you change the address static const int x = 10;

defined in the global scope?

It would be great to understand what's going on under the hood.

+3


source to share


1 answer


In C ++ 11 the requirements were relaxed (with additional clarifications in C ++ 14), now [temp.arg.nontype]/1

reads:

The template argument for a non-python template-template without a template must be one of the following:
 (...)
is a constant expression (5.19) that denotes the address of a complete object with static storage duration and external or internal link, or a function with external or internal link, including function templates and function template identifiers, but excluding non-static class members, expressed (ignoring parentheses) as &

id-expression, where id-expression is the name of an object or function, except which &

can be omitted if the name refers to a function, or an array and must be omitted if the matching template parameter is a reference



So, in C ++ 11, this compiles how you want:

template<int* i> void f(){};
static int x; // even without const
int main() {
    f<&x>();
}

      

+1


source







All Articles