Specialization of template templates

I want to write a specialization for a template function, where the type for which it specializes is itself a template type. (I am using C ++ 11 or higher.)

In the code example below, I have a common function convertToand a working specialization for int, which allows me to use convertTo<int>(s)(as shown). But I can’t understand how to write specializations for, for example std::set<T>. This is what I tried:

#include <string>
#include <sstream>
#include <set>
#include <unordered_set>
using namespace std;

// generic version
template<class T> T convertTo(const char* str) {
  T output;
  stringstream ss(str, stringstream::in);
  ss >> output;
  return output;
}

// specialization for int. works.
template <>
int convertTo<int>(const char* str) {
  return atoi(str);
}

template <>
template<class T> set<T> convertTo<set<T>>(const char* str) {
  set<T> S;
  // TODO split str by comma, convertTo<T>(each element) and put into S
  return S;
}

template <>
template<class T> unordered_set<T> convertTo<unordered_set<T>>(const char* str) {
  unordered_set<T> S;
  // TODO split str by comma, convertTo<T>(each element) and put into S
  return S;
}

int main() {
  float f = convertTo<float>("3.141");
  int i = convertTo<int>("123");
  set<int> os = convertTo<set<int>>("9,8,7,6");
  unordered_set<int> os = convertTo<unordered_set<int>>("9,8,7,6");
  return 0;
}

With g ++ 6.3.0, I get the error message:

 too many template parameter lists in declaration of ‘std::set<T> convertTo(const char*)’

So, I tried to comment on the lines template<>above the specialization attempts, but then I get:

non-class, non-variable partial specializationconvertTo<std::set<T, std::less<_Key>, std::allocator<_CharT> > >’ is not allowed

I do not understand. I was not going to write a partial specialization?

template<class Container>, . ( .)

, ?

+4
2

- , . ,

template <>
template<class T> set<T> convertTo<set<T>>(const char* str)

set<T>, .

- , template<> , , . , , (, set<T>) (, int), , .

, :

// Generic version
template <typename T>
class Converter {
  public:
    T operator() (const char* str) {
          T output;
          stringstream ss(str, stringstream::in);
          ss >> output;
          return output;
    }
};

template <>
class Converter<int> {
  public:
    int operator() (const char* str) {
        return atoi(str);
    }
};

// ...

template <typename T>
T convertTo(const char* str) {
    return Converter<T>{}(str);
}

, , .

+1

- . , . ; , , , . :

template <class T>
struct tag{}; // implementation detail

template<class T>
T convertTo(const char* str, tag<T>) {
  T output;
  stringstream ss(str, stringstream::in);
  ss >> output;
  return output;
}

int convertTo(const char* str, tag<int>) {
  return atoi(str);
}

template<class T>
set<T> convertTo(const char* str, tag<set<T>>) {
  set<T> S;
  // TODO split str by comma, convertTo<T>(each element) and put into S
  return S;
}

template<class T>
unordered_set<T> convertTo(const char* str, tag<unordered_set<T>>) {
  unordered_set<T> S;
  // TODO split str by comma, convertTo<T>(each element) and put into S
  return S;
}

template <class T>
T convertTo(const char * s) {
    return convertTo(s, tag<T>{});
};

convertTo, , , . , convertTo, , , , .

, tag , ADL/2- , .

+3

Source: https://habr.com/ru/post/1686050/


All Articles