I would like to have an array which has a length that depends on the parameter of my template, but I keep getting the "expected constant expression" error.
enum MyEnum
{
FIRST,
OTHER
};
template<MyEnum e>
struct MyTemplate
{
static const int arrSize;
int myArr[arrSize]; // error C2057: expected constant expression
// int myArr[e == FIRST ? 4 : 10]; // works, but isn't very readable...
};
template<>
const int MyTemplate<FIRST>::arrSize = 4;
template<>
const int MyTemplate<OTHER>::arrSize = 10;
The compiler I must use does not support constexpr, or any other C++ 11 features, and I also cannot pass the array size as a template parameter.
edit: I also must not use new.
Thanks
In some cases like this, I'll add a function get_array_size<e>(). Since you say you don't have constexpr, there's still decent possibilities:
//I call this a pseudo-template-function, but there's probably better names
template<MyEnum> struct GetArraySize; //compiler error for default
template<> struct GetArraySize<FIRST> {static const int value=4;};
template<> struct GetArraySize<OTHER> {static const int value=10;};
template<MyEnum e>
struct MyTemplate
{
static const int arrSize = GetArraySize<e>::value;
int myArr[arrSize];
};
http://coliru.stacked-crooked.com/a/f03a5fa94a038892
Are we reinventing the wheel here ? Enums are compile time constants. Just do this :
enum MyEnum
{
FIRST = 4,
OTHER = 10
};
template<MyEnum e>
struct MyTemplate
{
int myArr[e];
};
demo
Related
Why doesn't the below code compile? It says that S has to be const as one of the major errors.
template <int S>
class Array
{
int size;
int items [S];
public:
Array(void) :size(S){}
};
void main()
{
int S= 30;
Array <5+S> array;
}
Nontype template parameters must be constexpr, i.e., they have to be known at compile time. Hence, S must be declared as constexpr int.
Basically, I am trying to use a enum which could do bit operations and there is a template function could map the enum element to array index. In the operator overload function I need
a compile-time constant expression.
I need something like integral_constant, but that is in c11 not in c99 anyone know how to implement integral_constant in c99?
OR
Any other ways to create the enum could performance bit operation and index an array?
Thanks~
enum E
{
E_a=1,
E_b=2,
E_c=4,
E_d=8,
E_MAX=16,
};
// Template struct to compute the index
template<int N>
struct I
{
static const int idx = 1 + I<N/2>::idx;
};
template<>struct I<1>{ static const int idx= 0; };
//
class Data
{
static void Init()
{
data[E_a].value = 10;
data[E_b].value = 20;
data[E_c].value = 40;
data[E_d].value = 80;
}
Data* operator[](const E& e)
{
return &(Data::data[I<e>::idx]); // <-Here is the problem, template parameter should be a constant expression but e is a parameter, even it is constant it is not a expression
}
// member variables
void* value;
static Data data[I<E_MAX>::idx];
};
I would like to know how to initialize an array in a class whose values can be used in constant-expressions.
Here is an explanation of my problem :
// The goal : initializing an array for a class
// whose values can be used as normal static const
// (as template parameters for example)
class MyClass
{
public:
static const unsigned int value = 42; // <- No problem here
static const unsigned int array[3] = {100, 101, 102}; // <- How to initialize this static const array (with constexpr or metaprogrammation maybe ?)
template<unsigned int T> inline void f() {std::cout<<"Hello, my value is "<<T<<std::endl;} // <- Simple function for demonstration purposes
inline void fvalue() {f<value>();} // <- No problem here
inline void farray() {f<array[1]>();} // <- Big problem here
};
//const unsigned int Class1::array[3] = {100, 101, 102}; // <- If I do this, I will initialize the array but farray() will not compile
Is there any way to do this in C++ 2011 ? (with constexpr or metaprogrammation maybe ?)
Thank you very much !
EDIT : As the title specify it, I need the array to be a member of the class (not a global array).
Yes, you can make it constexpr..
Making it constexpr allows the static member to have more types than just integral or enumeration types, when it is initialized in-class. In particular, the member just needs to be of a literal type, and all expressions in the initializer must be constant expressions. So this is fine
class MyClass
{
public:
static constexpr unsigned int array[3] = {100, 101, 102};
template<unsigned int T> inline void f() {
std::cout<<"Hello, my value is "<<T<<std::endl;
} // <- Simple function for demonstration purposes
inline void farray() {f<array[1]>();}
};
// needs a definition out-of-class too. put it into a .cc file
constexpr unsigned int MyClass::array[3];
Just in case you were wondering what a meta-programming example could look like, here's an example:
#include <iostream>
template<size_t... values>
struct number_list;
template<size_t value, size_t... values>
struct number_list<value, values...>
{
static const size_t val = value;
typedef number_list<values...> next;
};
template<size_t index, typename NumList>
struct indexer
{
static const size_t val = indexer<index - 1, typename NumList::next>::val;
};
template<typename NumList>
struct indexer<0, NumList>
{
static const size_t val = NumList::val;
};
template<typename NumList>
class MyClass
{
public:
template<size_t T> inline void f()
{
std::cout << "Hello, my value is " << T << std::endl;
}
inline void farray() {f<indexer<1, NumList>::val>();}
};
int main()
{
MyClass<number_list<3, 5, 6>> a;
a.farray();
return 0;
}
When I try compiling
template<bool val>
struct boolean { static const bool value = val; };
template<typename T>
struct is_callable : boolean<sizeof((*(T*)0)()) >= 0> { }; // error!
int main(void) { bool b = is_callable<int (*)()>::value; }
I get:
error C2064: term does not evaluate to a function taking 0 arguments
see reference to class template instantiation 'is_callable<T>' being compiled
I'm pretty sure int (*)() is callable with 0 arguments... so why doesn't this compile?
The problem is not the use of int(). You can completely remove that from the example and get the same error. The problem is the sizeof expression itself when used as a non-type template argument. Example
template<bool val>
struct boolean { };
template<typename T>
struct is_callable : boolean<sizeof((*(T*)0)()) >= 0> // Error
{
void Test()
{
auto x = sizeof((*(T*)0)()) >= 0; // Compiles
}
};
Hopefully another C++ guy can come along and determine if this sizeof expression is simply illegal as a type argument or if this is just a limitation in the MS C++ compiler.
For me this works.
typedef int (*X)();
template<typename T>
struct is_callable : boolean<sizeof((*(X*)(T*)0)()) >= 0> { }; // works!
So, it looks like the compiler is not sure that you will always pass a function pointer to T when you instantiate the template class !. So, force the compiler with an explicit cast.
[Edit] : Also, on further thinking, I don't understand what you are really trying to do. Are you trying to measure the size of a function pointer which takes a single parameter? How this is going to be different for functions with different return types? Why do you need template at all for a constant expression (which is sizeof(void*))?
Please check this thread for more understanding
What is guaranteed about the size of a function pointer?
You could just use simple template specialization.
#include <stdio.h>
template<typename T>
struct func_with_zero_args { static const bool value = false; };
template<>
struct func_with_zero_args <int (*)()> { static const bool value = true; };
#define STRINGIFY(t) "" #t
#define TEST(t) printf(STRINGIFY(t) ": %s\n", (func_with_zero_args<t>::value ? "yes" : "no"));
int
main(int argc, const char* argv[])
{
TEST(void);
TEST(void (*)(void));
TEST(void (*)(int));
TEST(int (*)(void));
TEST(int (*)(int));
return 0;
}
Generates (using g++ (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3)
void: no
void (*)(void): no
void (*)(int): no
int (*)(void): yes
int (*)(int): no
Atm i have sth like that:
template<int n>
struct Pow
{
enum{val= Pow<n-1>::val<<1};
};
template<>
struct Pow<0>{
enum{val =1};
};
I can acess data like Pow<30>::val. It's good but i want do like this
int main()
{
Pow<30>::val;
and then use variable to
access all of value <0,30>
I knew that i can use array and dynamic programming but can i do that in this way?
Sorry for English.
Using C++0x variadic templates:
template<int... Indices>
struct powers {
static const int value[sizeof...(Indices)];
typedef powers<Indices..., sizeof...(Indices)> next;
};
template<int... Indices>
const int powers<Indices...>::value[sizeof...(Indices)] = { Pow<Indices>::val... };
template<int N>
struct build_powers {
typedef typename build_powers<N - 1>::type::next type;
};
template<>
struct build_powers<1> {
typedef powers<0> type;
};
and then:
int
main()
{
// we want [0..30] inclusive so pass 31 as exclusive upper limit
typedef build_powers<31>::type power_type;
// 0..30 is 31 powers in all
typedef const int array_type[31];
array_type& ref = power_type::value;
// ref[0] .. ref[30] are the values of Pow<0>::val .. Pow<30>::val
}
So that's with using an array but without dynamic initialization. Since you want the result as a variable and not for TMP I feel this is adequate.
When you do Pow<30>::val; you will instantiate the top of your two templates, then when it get's to zero it will instantiate the specialization, and only the final result will be visible at runtime, since templates are resolved at compile time