Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static const member initialization in templated class

I have a problem regarding 'static const' member initialization. In a templated class I define a const member and initialize it outside the class.
When I include the .h file where this class is implemented in multiple .cpp files, I get an LNK2005 error (I'm using VS2010) that says the constant is already defined.

// List.hpp
template <class T>
class List {
    static const double TRIM_THRESHOLD;
};

template <class T>
const double List<T>::TRIM_THRESHOLD = 0.8;

I tried putting the member initialization in a .cpp file, but then I get a linker error saying that the constant is not defined at all. If the list is not templated and I put the initialization in a .cpp file, all is fine.
Is there any solution for this situation? I have #ifdef/define clauses around the file already, and it's definitely not a solution.

like image 737
Gratian Lup Avatar asked Jul 22 '10 08:07

Gratian Lup


People also ask

How do you initialize a const member of a class?

To initialize the const value using constructor, we have to use the initialize list. This initializer list is used to initialize the data member of a class. The list of members, that will be initialized, will be present after the constructor after colon. members will be separated using comma.

Can static members be const?

A static data member can be of any type except for void or void qualified with const or volatile. You cannot declare a static data member as mutable.

How to initialize const in c++?

A constant variable must be initialized at its declaration. To declare a constant variable in C++, the keyword const is written before the variable's data type. Constant variables can be declared for any data types, such as int , double , char , or string .


1 Answers

You should define the constant in a source file not a header (so it only gets defined once) since this is a template which you need to keep in the header(and all instances have the same value) you can use a common base class.

class ListBase {
protected:
    ListBase() {} // use only as base 
    ~ListBase() { } // prevent deletion from outside
    static const double TRIM_THRESHOLD;    
};

template <class T>
class List : ListBase {  
};

// in source file
double ListBase::TRIM_THRESHOLD = 0.8;

Another option is to have it as a static function:

    static double trim_threashold() { return 0.8; }

Edit: If your compiler supports C++11 you make your static method a constexpr function so that it has all the optimization opportunities that using the value directly has.

like image 175
Motti Avatar answered Nov 15 '22 08:11

Motti