简体   繁体   中英

Type-dependent constant in template function

I want a static array in a templated function whose length depends on the type with which the function is specialized. My first attempt was:

Header:

template<typename T>
struct Length {
    const static size_t len;
};

template<typename T>
void func(){
  static T vars[Length<T>::len]; // len not const. according to compiler!
  // ...
}

Source file:

template<> const size_t Length<double>::len = 2;
template<> const size_t Length<float>::len = 1;
// ...

However, g++ does not compile this and complains

error: storage size of 'vars' isn't constant

So, what exactly is the problem here? I know that the size of a fixed-length array needs to be a constant and known on compile time, but that seems to be the case here. When I write

const size_t len = 2;

void func(){
    static double vars[len];
}

it compiles without problems.

Question:

What is wrong with the code and which alternatives are there for achieving the desired behavior? I would not like to allocate the memory during runtime...

For a const variable to be considered a compile-time constant (formally, a constant expression ), its value must be available at point of use. Which means the specialised definitions would have to go to the header file.

If done as just specialisations of the member, as you did, I believe that would give you a multiple-definition error. You should be fine with specialising the entire class template, and keeping the static member definition inline:

template<typename T>
struct Length;

template <>
struct Length<double>
{
  static const size_t len = 2;
};

As a side note, your program was originally invalid: an explicit specialisation must be declared before use. Which means you'd have to at least declare the specialisation of len in the header (or everywhere you intended to use it).

The following code compiles fine for me with g++ 4.6.3 and produces the output

2
1

array.cpp :

#include <cstddef>
#include <iostream>

template<typename T>
struct Length {
    const static size_t len;
};

template<typename T>
void func(){
  static T vars[Length<T>::len]; 
  std::cout << (sizeof(vars) / sizeof(*vars)) << std::endl;
}

template<> const size_t Length<double>::len = 2;
template<> const size_t Length<float>::len = 1;

int main(){
  func<double>();
  func<float>();
}
$ make array
g++     array.cpp   -o array
$ ./array 
2
1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM