193

I'd like to do this:

template <typename T> struct S { ... static double something_relevant = 1.5; }; 

but I can't since something_relevant is not of integral type. It doesn't depend on T, but existing code depends on it being a static member of S.

Since S is template, I cannot put the definition inside a compiled file. How do I solve this problem ?

3
  • also applies to std::string type Commented Jul 9, 2018 at 12:49
  • Since c++11 the keyword inline has changed so that static variables can be initialized at the point of declaration. So the declaration for this would look like "inline static double something_relevant = 1.5;" Commented Apr 3, 2019 at 14:27
  • 3
    @user8991265 I believe inline variables are available since C++17, not C++11. Commented Apr 20, 2020 at 10:49

3 Answers 3

256

Just define it in the header:

template <typename T> struct S { static double something_relevant; }; template <typename T> double S<T>::something_relevant = 1.5; 

Since it is part of a template, as with all templates the compiler will make sure it's only defined once.

Sign up to request clarification or add additional context in comments.

12 Comments

@sbi: doesn't it violate the one definition rule ?
No, not if we're talking templates. Otherwise function templates would do so, too.
@sbi, @Prasoon: actually Prasoon seems to be the first. But I still accept sbi's because of the comment about the ODR (which was my primary concern).
@Johannes: Dammit, I'm here for a year and I didn't know that! What else am I missing? (I still remember the shame when I discovered that the two numbers that appear when I click on the number of votes aren't a bug, but a feature.) <goes_playing> Wow, when I hover over your name, I see your rep! I didn't know that one either. @Prasoon: No, you're right, I iteratively arrived at where it is now. (That's why I up-voted your answer, BTW.)
@sbi - To muddy the waters, how do we initialize 5 or 6 specializations of T? I've been trying the {simple|obvious} answer at How to initialize a static member of a parametrized-template class, but Clang keeps failing the link due to mulitply defined symbols because the header is used in several source files. In our case the class variable is static const and it is like things are escaping translation unit scope.
|
95

Since C++17, you can now declare the static member to be inline, which will define the variable in the class definition:

template <typename T> struct S { ... static inline double something_relevant = 1.5; }; 

live: https://godbolt.org/g/bgSw1u

3 Comments

This is an excellent answer. Short and precise. See also en.cppreference.com/w/cpp/language/static#Static_data_members for more information.
One wonders why the standards committee felt it necessary to require an extra keyword instead of just making the previously illegal static declaration legal.
This is not possible if the type of the member is of the templated class itself, as the class is not yet fully defined.
41

This will work

template <typename T> struct S { static double something_relevant; }; template<typename T> double S<T>::something_relevant=1.5; 

3 Comments

I didn't define the something_relevant variable(I removed template<typename T> double S<T>::something_relevant=1.5;) compiler throwing error.Can you please tell me what is the reason?
This will introduce a copy of the variable in each module that include these lines. And how can one make sure that the variable is present only in one shared module, and other modules reference it?
What syntax should I use to specialize this expression to get different values for class A vs class B?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.