gmygmy
gmygmy

Reputation: 61

"could not convert template argument" error for pointer parameters even with cast

Say I have a template class declared as follows:

template< int *x > struct y { int *b; y() { b = x; }}

I do need the template parameter to be a constant memory address - it is an embedded code. If I try to instantiate it like this: (compiler is gcc 4.8.1 with -std=gnu++11)

y< 1 > c;   

I will get an error "could not convert template argument '1' to 'int*'" and that's fine and according to standard. I understand it.

My problem is that casting to pointers does not work either:

y< (int *)1 > d;
y< reinterpret_cast<int *>(1) > e;

error: could not convert template argument '1u' to 'int*'

in both cases. Why is that? Template argument is already converted, isn't it?

Upvotes: 6

Views: 1556

Answers (2)

rici
rici

Reputation: 241791

I'm not sure exactly what your requirements are, but I suppose you're trying to model specific hardware registers. Will this satisfy your needs?

#include <cstdint>
template< uintptr_t x > struct y {
  int *const b;
  y() : b(reinterpret_cast<int*>(x)) {}
};      

int main() {
  y< 42 > c;
  return *c.b;  
}

Upvotes: 1

quantdev
quantdev

Reputation: 23803

This is not allowed as per the C++ standard, section §14.3.2

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

  • an integral constant-expression of integral or enumeration type; or
  • the name of a non-type template-parameter; or
  • the address of an object or function with external linkage, including function templates and function template-ids but excluding non-static class members, expressed as & id-expression where the & is optional if the name refers to a function or array, or if the corresponding template-parameter is a reference; or
  • a pointer to member expressed as described in 5.3.1

Solution :

Use a variable with external linkage as the template parameter :

template< int *x > struct y 
{
    int *b;
    y() { b = x; }
};

extern int i;     // Extern
static int j = 1; // Static
int z = 1;        // Global

int main() {
    y< &i > c1;
    y< &j > c2;
    y< &z > c3;
    return 0;
}

Live example here.

Upvotes: 4

Related Questions