Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem with C++ Partial Template Specialization

I have a situation similar to this:

template<class A, class B>
class MyClass<A, B>
{
  ...
  static A RARELY_USED_A;
}

// Seems to work but does not cover all possible cases, since 
// there may be instances of A that have no numeric limits.
template<class A, class B>
A MyClass<A, B>::RARELY_USED_A= std::numeric_limits<A>::max();

From what I saw this seems to work. However, strings may be used as A under some circumstances and so I thought I'd simply create a specialization for this special case.

// Does not complile
template<class B>
string MyClass<string, B>::RARELY_USED_A= "";

unfortunately this does not complie properly with error msg:

error: template definition of non-template 'std::string MyClass<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, B>::RARELY_USED_A'

Note that, on the othre hand, a full specialization seems to work (untested at runtime but compiles)

// This complies but is not gernic enough and hence useless to me
template<>
string MyClass<string, string>::RARELY_USED_A= "";

I assume, I must be doing something wrong. I would be really grateful if you could point out what exactly it is. I thought partical specializations were supposed to work this way.

Thanks a lot in advance.

e: edited the name of the DEFAULT_A to RARELY_USED_A, because I thought that "default" was misleading somehow

like image 408
b.buchhold Avatar asked Sep 27 '26 16:09

b.buchhold


2 Answers

Use inheritance to reuse and specialize without duplicating all the common code:

template<typename A>
struct RarelyUsedShared
{
    static A RARELY_USED_A;
};

template<typename A>
A RarelyUsedShared<A>::RARELY_USED_A = std::numeric_limits<A>::max();

template<>
string RarelyUsedShared<string>::RARELY_USED_A = "";

template<typename A, typename B>
class MyClass<A, B> : RarelyUsedShared<A>
{
  ...
};

Note that this will result in sharing the member across various B, which is ok if the member should be const. If not, the helper can take two template parameters, and you can partially specialize it:

template<typename A, typename B>
struct RarelyUsedNotShared
{
    static A RARELY_USED_A;
};

template<typename A, typename B>
A RarelyUsedNotShared<A, B>::RARELY_USED_A = std::numeric_limits<A>::max();

template<typename B>
struct RarelyUsedNotShared<string, B>
{
    static A RARELY_USED_A;
};

typename<typename B>
string RarelyUsedNotShared<string, B>::RARELY_USED_A = "";

template<typename A, typename B>
class MyClass<A, B> : RarelyUsedNotShared<A, B>
{
  ...
};
like image 154
Ben Voigt Avatar answered Sep 30 '26 05:09

Ben Voigt


You need to give a partial specialization to your entire class, not just a single member.

like image 28
n. 1.8e9-where's-my-share m. Avatar answered Sep 30 '26 05:09

n. 1.8e9-where's-my-share m.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!