3

Given the following class forward declaration in a header file:

template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
class context
{
public:
    context();
// ....
private:
// ....
    T data;
}

How can I define the constructor (or any other member function) in the cpp file? Tried everything I can think of but nothing matched....

This other question was brought to my attention Why can templates only be implemented in the header file? and I have successfully used the methodology suggested in the accepted answer in multiple places in my project, however I can not find a way to represent the second template parameter in any way... that question does not provide enough information to do that. The problem is here the second template parameter makes that either incompatible with the suggested way there or I just could not find the appropriate syntax to represent it, if my class would have just the first parameter it would answer it...

P.S. Sorry if this is a duplicate, I really tried to find a similar question just could not find the appropriate terminology to find a match.

xception
  • 4,241
  • 1
  • 17
  • 27
  • Template class members don't go in cpp files. They have to go in the header with the rest of the class, because templates are not "real code". They are *templates* for code, and the compiler needs to have the whole thing available to create the real code when needed. I think the question still stands if you need to declare the class members in the header and then define them later in the header. – HTNW Nov 27 '19 at 08:36

1 Answers1

5

To supply an out of class definition, the template parameter list must match.

template<typename T, std::enable_if_t<std::is_integral_v<T>, int> N>
context<T, N>::context() {
}

The parameter type is std::enable_if_t<std::is_integral_v<T>, int> in the class template definition. And that's exactly what needs to be the type of the parameter in the out of class definition.

As an aside, I don't see a benefit for the check being where it is currently. Unlike function templates, where this may affect overload resolution, class templates don't benefit much if at all from the mechanism. IMO it would be preferable to simply add a static assertion to the class template declaration

template<typename T>
class context {
    static_assert(std::is_integral_v<T>, "Must be initialized with an integral type");
    // ...
};

Then the out of class member declarations become much more straight forward. And error messages about bad template arguments are much more readable.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • thanks, that works, for some reason it never crossed my mind to name the second template parameter, also thank you for the aside information, I'll take it into consideration – xception Nov 27 '19 at 08:48