How to define a template function for a base-type and other unrelated types?

100 views Asked by At

I want to implement family of functions like this:

template <class T>
T GetValue(const TObject& obj, const std::string& field);

template <>
int GetValue<int>(…) {…}

template <>
float GetValue<float>(…) {…}

// Any DerivedString is derived from BaseString
template <class DerivedString>
DerivedString GetValue<DerivedString>(const TObject& obj, const std::string& field) {…} // ← how?

Where the last specialization (or something else) will be called for all types derived from some BaseString type.

The main goal is to be able to call:

GetValue<int>(…);
GetValue<float>(…);
GetValue<BaseString>(…);
GetValue<StrongStringType1>(…);
GetValue<StrongStringType2>(…);

Without specializing function for each derived type.

1

There are 1 answers

0
HolyBlackCat On

Function templates can't be partially specialized.

Your options are:

  1. One big function with a bunch of if constexpr in it.
  2. Overloading the function instead of specializing.
  3. Wrapping the function in a class template (making the function itself non-template), and specializing the whole class. You can then provide a function that calls into it, for a nicer syntax.

I'd go with (3).

For (2), to make the "any derived class" overload, any form of SFINAE will work, e.g.:

template <std::derived_from<MyStringBase> DerivedString>
DerivedString GetValue<DerivedString>(const TObject &obj, const std::string &field) {...}

For int and float, I'd perhaps replace specializations with overloads too, just to be consistent:

template <std::same_as<int>>
int GetValue(const TObject& obj, const std::string& field);