Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to access values of non-type template parameters in specialized template class?

Is it possible to access values of non-type template parameters in specialized template class?

If I have template class with specialization:

   template <int major, int minor> struct A {
       void f() { cout << major << endl; }
   }

   template <> struct A<4,0> {
       void f() { cout << ??? << endl; }
   }

I know it the above case it is simple to hardcode values 4 and 0 instead of using variables but what I have a larger class that I'm specializing and I would like to be able to access the values.

Is it possible in A<4,0> to access major and minor values (4 and 0)? Or do I have to assign them on template instantiation as constants:

   template <> struct A<4,0> {
       static const int major = 4;
       static const int minor = 0;
       ...
   }
like image 507
stefanB Avatar asked Jul 22 '09 00:07

stefanB


People also ask

Can we use non-type parameters as argument templates?

A non-type template argument provided within a template argument list is an expression whose value can be determined at compile time. Such arguments must be constant expressions, addresses of functions or objects with external linkage, or addresses of static class members.

What are non-type parameters for templates?

A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument. A non-type parameter can be any of the following types: An integral type. An enumeration type.

Can template parameters have default values?

Just like in case of the function arguments, template parameters can have their default values. All template parameters with a default value have to be declared at the end of the template parameter list.

Can a template be a template parameter?

Templates can be template parameters. In this case, they are called template parameters. The container adaptors std::stack, std::queue, and std::priority_queue use per default a std::deque to hold their arguments, but you can use a different container.


2 Answers

This kind of problem can be solved by having a separate set of "Traits" structs.

// A default Traits class has no information
template<class T> struct Traits
{
};

// A convenient way to get the Traits of the type of a given value without
// having to explicitly write out the type
template<typename T> Traits<T> GetTraits(const T&)
{
    return Traits<T>();
}

template <int major, int minor> struct A 
{ 
    void f() 
    { 
        cout << major << endl; 
    }   
};

// Specialisation of the traits for any A<int, int>
template<int N1, int N2> struct Traits<A<N1, N2> >
{
    enum { major = N1, minor = N2 };
};

template <> struct A<4,0> 
{       
    void f() 
    { 
        cout << GetTraits(*this).major << endl; 
    }   
};
like image 141
Andrew Shepherd Avatar answered Sep 27 '22 20:09

Andrew Shepherd


Not really an answer to your question, but you could enumerate them, viz:

enum{
 specialisationMajor=4,
 specialisationMinor=0
};

template <> struct A<specialisationMajor,specialisationMinor> {
    static const int major = specialisationMajor;
    static const int minor = specialisationMinor;
    ...
}
like image 42
Dave Gamble Avatar answered Sep 27 '22 19:09

Dave Gamble