3

Does C++ allow templates to take the address of a variable with static storage as a parameter? Since a memory address is integral and those with static storage are known at compile time it seems possible.

I found this question showing that this works for int*.

Is it legal C++ to pass the address of a static const int with no definition to a template?

So far, I haven't convinced my compiler accept pointers to other types like char*.

Can templates be specialized on static addresses in general? If not, why?

Edit: I should have been more explicit. Here is some code that compiles for me using g++ 4.9.

#include <iostream>

template<int* int_addr>
struct temp_on_int{
    temp_on_int() {}
    void print() {
        std::cout << *int_addr << std::endl;
    }
};


template<char* str_addr>
struct temp_on_string{
    temp_on_string() {}
    void print() {
        std::cout << str_addr << std::endl;
    }
};

static int i = 0;
static char j = 'h';
// static char* k = "hi";

int main() {

    temp_on_int<&i> five;
    i = 6;
    five.print();

    temp_on_string<&j> h;
    h.print();

    // temp_on_string<k> hi;
    // hi.print();
}

Commented out is something that won't compile with g++ 4.9. The code as shown won't compile on coliru.

http://coliru.stacked-crooked.com/a/883df3d2b66f9d61

How I compiled:

g++ -std=c++11 -Og -g -march=native -Wall -Wextra -pedantic -ftrapv -fbounds-check -o test16 test16.cpp

The error I get when I try to compile the commented portion:

test16.cpp:33:17: error: the value of 'k' is not usable in a constant expression temp_on_string hi; ^ test16.cpp:22:14: note: 'k' was not declared 'constexpr' static char* k = "hi"; ^ test16.cpp:33:18: error: 'k' is not a valid template argument because 'k' is a variable, not the address of a variable
temp_on_string hi;

Community
  • 1
  • 1
Praxeolitic
  • 22,455
  • 16
  • 75
  • 126
  • Are you saying that that code is accepted by your compiler, but if you change `int` to `char`, and change nothing else, your compiler rejects it? –  Sep 20 '14 at 07:02
  • The question was unclear about that - edited. – Praxeolitic Sep 20 '14 at 07:13

3 Answers3

6
14.3.2
  Template non-type arguments [temp.arg.nontype]
    1
      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 a complete object with static storage duration and external or internal linkage or a function with external or internal linkage
     [...]

Since k is not a constant expression, you cannot use it as a template argument.

If you replace the declaration of k with

static char k[] = "hi";

clang++ compiles it. g++ does not; this is IMO a bug in g++.

If k is declared as

namespace { char k[] = "hi"; }

then g++ compiles it too.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
1

Yes, but only static addresses with linkage will initialize a pointer template parameter. Your char * probably didn't work with a string literal, because those have no linkage.

Use a named, extern variable instead.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • Could you explain just a bit more? What do you mean by no linkage? Is that distinct from static linkage? Are these rules about pointer template parameters explicitly stated in the standard or do they arise as a consequence of something else? – Praxeolitic Sep 20 '14 at 07:19
  • @Praxeolitic "No linkage" is due to the string literal having no name. The rule was quoted by n.m. – Potatoswatter Sep 20 '14 at 07:36
0

I've never seen that but, i don't think so... i tried to compile it, but it doesn't work, i can't really see the use, but that doesn't mean it is impossible...

To my knowing, static variables need to be define, so they can be init with something, so it can be used (at least that is what most times do)... and well with static functions with template there is no problem... just the static variable, unless you find a way to init a template static variable, with out knowing the template type, than it might be done...

ekiim
  • 792
  • 1
  • 11
  • 25