0

Why I can't pass this pointer as a template argument:

template <const char* T>
struct MyStruct
{};

int main()
{

    static constexpr const char* func_name = nullptr; 
    MyStruct<func_name>{}; // Works
    static constexpr const char* func_name2 = __func__;
    MyStruct<func_name2>{};
    // A template argument may not reference a non-external entity
    // MyStruct: invalid expression as a template argument for 'T'
//error: the address of ‘__func__’ is not a valid template argument
}

I want to pass the name of the function as a template argument, and no workaround seems possible. Why?

According to the GCC documentation:

The identifier __func__ is implicitly declared by the translator as if, immediately following the opening brace of each function definition, the declaration

static const char __func__[] = "function-name";

So it's as if it's declaring that inside the function, then I assign my constexpr const char* to it, and then pass it as the template argument. That should work, does it not?

I know that there are gotchas when it comes to const char* as a template argument. Before I was having trouble with passing a string literal (they're not allowed as template arguments). But in this case it seems I'm passing the address of a static array, which is a valid argument, no?

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
Zebrafish
  • 11,682
  • 3
  • 43
  • 119
  • Does this answer your question? [How to declare constexpr C string?](https://stackoverflow.com/questions/46100310/how-to-declare-constexpr-c-string) – dewaffled Aug 31 '21 at 11:42
  • 1
    @dewaffled I know how to declare it constexpr, I did in my code, but I think the problem is that it's pointing to what __func__ declares, and it won't accept that as a template argument. – Zebrafish Aug 31 '21 at 11:45
  • It has little to do with `__func__` because if you replace that by a string constant, it's still rejected. – Thomas Aug 31 '21 at 11:50
  • Presumably it's because *a template argument may not reference a non-external entity*. – user253751 Aug 31 '21 at 11:51
  • @Zebrafish The answer you've gotten seems to be pretty spot on, doesn't it? – Ted Lyngmo Sep 03 '21 at 13:38

1 Answers1

3

__func__ is explicitly disallowed.

[temp.arg.nontype]

3 For a non-type template-parameter of reference or pointer type, or for each non-static data member of reference or pointer type in a non-type template-parameter of class type or subobject thereof, the reference or pointer value shall not refer to or be the address of (respectively):

  • [...]
  • a predefined __func__ variable ([dcl.fct.def.general]), or
  • [...]

So GCC is correct.

You should also note that the GCC documentation states it is "as if" there is such a variable. There doesn't have to be one.

The content and exact whereabouts of __func__ is implementation defined, so just like string literals it is not constrained enough to play well with the one-definition rule when determining the linkage of templated entities.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458