Reputation: 59
So, I'm wishing to be able to have a static const compile
time struct that holds some value based on a string by using
templates. I only desire up to four characters. I know that
the type of 'abcd' is int
, and so is 'ab','abc', and although
'a' is of type char
, it works out for a template<int v> struct
What I wish to do is take sizes of 2,3,4,5 of some const char, "abcd" and have the same functionality as if they used 'abcd'. Note that I do not mean 1,2,3, or 4 because I expect the null terminator.
cout << typeid("abcd").name() << endl;
tells me that the type for
this hard coded string is char const [5]
, which includes the null
terminator on the end.
I understand that I will need to twiddle the values as characters, so they are represented as an integer.
I cannot use constexpr
since VS10 does not support it (VS11 doesn't either..)
So, for example with somewhere this template defined, and later the last line
template <int v> struct something {
static const int value = v;
};
//Eventually in some method
cout << typeid(something<'abcd'>::value).name() << endl;
works just fine.
I've tried
template<char v[5]> struct something2 {
static const int value = v[0];
}
template<char const v[5]> struct something2 {
static const int value = v[0];
}
template<const char v[5]> struct something2 {
static const int value = v[0];
}
All of them build individually, though when I throw in my test,
cout << typeid(something2<"abcd">::value).name() << endl;
I get
'something2' : invalid expression as a template argument for 'v'
'something2' : use of class template requires template argument list
Is this not feasible or am I misunderstanding something?
Upvotes: 0
Views: 2000
Reputation: 1851
There is a way to get close to what you are wanting. Possibly this will work for you, although it adds an extra level of code to be maintained.
It requires defining const char arrays with external linkage, then using the names of those arrays to instantiate classes from the templates. Of course in real use this code would be separated into various .h and .cpp files.
extern const char a[] = "a";
extern const char b[] = "b";
extern const char ab[] = "ab";
extern const char abc[] = "abc";
template <const char * const T> class Test
{
public:
Test() {str = typename T;};
private:
const char * str;
};
SomeFunction()
{
Test<a> A;
Test<b> B;
Test<ab> AB;
Test<abc> ABC;
}
Upvotes: 0
Reputation: 88215
14.1 lists the acceptable types of non-type template arguments:
— integral or enumeration type,
— pointer to object or pointer to function,
— lvalue reference to object or lvalue reference to function,
— pointer to member,
Arrays don't fit under any of these categories.
14.3.2/1 lists categories of what's permitted as template arguments and 14.3.2/2 goes on to say:
Note: A string literal (2.14.5) does not satisfy the requirements of any of these categories and thus is not an acceptable template-argument.
Therefore you cannot do what you're trying to do.
Upvotes: 1
Reputation: 17720
you cannot, from the standard.
14.3.2.1:
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 .
Upvotes: 0