Bioliquid
Bioliquid

Reputation: 191

Nested class template specialization issue

I have a enum Type that describes methods of parsing some objects. E.g. I can parse "len100" as a string either a enumeration. Nested struct Native takes a template argument that describes a type of the variable in which value will be contained. E.g. "len100" can be saved to string or uint. But this code gives me an error:

"invalid use of incomplete type 'struct Evaluator<(Type)3>::Native<T>'"

on this line:

T Evaluator<Type::jarray>::Native<T>::eval() {

This happens also with the vector specialization. How can I fix this problem and is there a better solution to handle this task?

enum class Type
{
      juint
    , jstring
    , jenum
    , jarray
};

template<Type type>
struct Evaluator
{
    template<typename T>
    struct Native {
        static T eval();
    };
};

template<>
template<typename T>
T Evaluator<Type::jarray>::Native<T>::eval() {
    cout << "primitive" << endl;
    return T{};
}

template<>
template<typename T>
T Evaluator<Type::jarray>::Native<vector<T>>::eval() {
    cout << "vector" << endl;
    return T{};
}

int main() {
    Evaluator<Type::jarray>::Native<vector<int>>::eval();
}

Upvotes: 2

Views: 105

Answers (1)

Oliv
Oliv

Reputation: 18051

For the first case you try to provide a member specialization of an unspecialized template member of a specialization.

This is forbidden. The act of specializing must be descending, from the encapsulating class toward its member. First you specialize the encapsulating class or specialize the encapsulating class for one of its member template. Then you can specialize this member template, and so on.

The second error is because you try to provide a specialization of the member eval for an undeclared partial specialization Native<vector<int>>.

So to fix your issue, the only option is to specialize the entire template class Native for the specialization Evaluator<Type::Jarray>. Then you must also define a partial specialization for the previously defined member template Native (itself is a member specialization ... ouch!):

#include <iostream>
#include <vector>

enum class Type
{
      juint
    , jstring
    , jenum
    , jarray
};

template<Type type>
struct Evaluator
{
    template<typename T>
    struct Native {
        static T eval();
    };
};

//here we provide a member specialization for Evaluator
//the struct Evaluator is not entirely specialized
//it is specialized for only one of its member.
//and this member is an template
template<>
template<typename T>
struct Evaluator<Type::jarray>::Native{
    static T eval(){
      std::cout << "primitive" << std::endl;
      return T{};
      }
};

//Here we declare a partial specialization of the
//member `Native` of `Evaluator` specialized just above.
template<>
template<typename T>
struct Evaluator<Type::jarray>::Native<std::vector<T>>{
    static T eval() {
      std::cout << "vector" << std::endl;
      return T{};
     }
  };


int main() {
    Evaluator<Type::jarray>::Native<std::vector<int>>::eval();
    Evaluator<Type::jarray>::Native<int>::eval();
}

Upvotes: 4

Related Questions