0

I have the following code:

template<typename T>
class Data
{
public:
    int size() const;
private:
    T m_data;
};

I want to implement the size() method using template specialisation methods. For a std::string it would look like this (in the .cpp):

template<>
int Data<std::string>::size() const
{
    // code here
}

Now I would like to make a single specialisation for all arithmetic types. My initial thought was (in the .hpp):

template<typename T, 
         typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
int Data<T>::size() const
{
    // code here
}

However that throws a '/Data.hpp:29:1: Too many template parameters in template redeclaration'. How can I make a partial specialisation for all arithmetic types?

Edit: Correctly working by following cppreference's example:

template<typename T, typename Enable = void>
class Data
{
public:
    int size() const { std::cout << "generic\n"; return 0; }

protected:
    T m_data;
};

template<typename T>
class Data<T, typename std::enable_if<std::is_arithmetic<T>::value>::type>
{
public:
    int size() const { std::cout << "arithmetic\n"; return 0; }

protected:
    T m_data;
};

Doing:

Data<int> intData;
intData.size();

Results in 'arithmetic' being printed

Cherub
  • 17
  • 4
  • You need to specialize the whole class. Partial specialization of individual members is not possible. See linked duplicates. – walnut Mar 30 '20 at 16:18
  • I find it difficult to apply those examples to my case. From what I gather, I rename 'Data' to 'Base' and make a new Data class which derives from Base but uses the std::is_arithmetic template. This, however, gives me an 'Too many template parameters in template redeclaration' error. – Cherub Mar 30 '20 at 17:05
  • Could you edit a demonstration of this issue into your question? (But don't remove the original content.) What you described should work if you use the correct partial specialization syntax. Click [edit] to edit the question. – walnut Mar 30 '20 at 23:45
  • Sure - thank you for your help. I've editted the question. I realise I might want to use virtual and override on the size() method, but I don't think that's going to help with the template specialisation problem. – Cherub Mar 31 '20 at 10:03
  • That is not the correct syntax for partial specialization. See the `A` class in the example on [this cppreference](https://en.cppreference.com/w/cpp/types/enable_if) page for a demonstration of how to use partial specialization with `enable_if`. You do not nee to make anything `virtual`. The base class is not supposed to be used directly. – walnut Mar 31 '20 at 10:19
  • The cppreference page was really helpful to get the syntax right. There are no more errors however it doesn't do what I would expect it to, see the edits. Changing the Data to Data works, however I'm trying to get the specialization based on that first parameter. – Cherub Mar 31 '20 at 11:51
  • `, T` in the `enable_if`'s arguments doesn't belong there. Just remove it. – walnut Mar 31 '20 at 12:14
  • Thank you, that works! I've editted the question with the solved answer. – Cherub Mar 31 '20 at 16:35

1 Answers1

-1

Instead of specializing the method you could specialize the contents, e.g.:

template<typename T>
int Data<T>::size() const
{
         if constexpr( std::is_same_v<char, T> )     return ::strlen(m_data);
    else if constexpr( std::is_same_v<wchar_t, T> )  return ::wcslen(m_data);
    else if constexpr( std::is_arithmetic_v<T> )     return <whatever for ints and floats>;
    else                                             return <whatever for other types>;
}
Chris Kushnir
  • 227
  • 2
  • 4