Does static object in a template function have lin

2019-08-28 03:37发布

问题:

This question refers to my previous question: clang does not compile my code, but g++ does. From my research, the issue at stake boils down to linkage, does the static variable data have linkage in the sample below (it compiles with g++-4.8.1)? How come it has linkage (I would not otherwise be able to instantiate with a non-type template parameter)?

template <int const* ptr>
void foo()
{
}

typedef void (*func_type)();

template <int = 0>
void run_me()
{
  static int data;

  func_type const f1 = foo<&data>;
  // auto f2 = foo<&data>; // doesn't work with gcc
  // foo<&data>();         // doesn't work with gcc
}

int main(int, char*[])
{
  run_me();

  return 0;
}

Obligatory quote from the standard:

A template-argument for a non-type, non-template template-parameter shall be one of: ...

— a constant expression (5.19) that designates the address of an object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as & id-expression, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; or ...

回答1:

Surely a static variable declared in a function (whether or not it is a template function) has no linkage.

§3.5 para. 8: "except as noted, a name declared at block scope (3.3.3) has no linkage"

The only exceptions listed in that clause, as far as I can see, are provided in para. 6: "The name of a function declared in block scope and the name of a variable declared by a block scope extern declaration have linkage."

However, it's possible that 14.3.2 might be loosened at some point.

Daniel Krügler submitted DR 1451 on 2012-02-01:

According to 14.3.2 [temp.arg.nontype] paragraph 1 bullet 3, only objects with linkage can be used to form non-type template arguments. Is this restriction still needed? It would be convenient to use block-scope objects as template arguments.

The DR was closed on the basis that it is an extension request and should be dealt with by the Evolution Working Group. It seems to have been included in n3413, "Allowing arbitrary literal types for non-type template parameters".

So it's certainly conceivable that one or more C++ compilers might choose to implement a looser restriction on non-type template parameters.