Home > Blockchain >  identical full template specialization
identical full template specialization

Time:01-13

What is the correct syntax to fully specialize a template class, to an already defined specialization?

E.g., in the code below, how can I declare A<2> as an alias to A<0>?

template <int I>
struct A;

template <>
struct A<0> { int x; };

template <>
struct A<1> { int y; };

template <>
using A<2> = A<0>; // error: expected unqualified-id before 'using'

Note: for the code above, it would be enough to specialize A<1> and define the non-specialized A like A<0>:

template <int I>
struct A { int x; };

template <>
struct A<1> { int y; };

but this would not work if you a more complex situation, where for a set of values you have a specialization, for another set of values another specialization, etc...

CodePudding user response:

Not sure I understood your problem, since you described it by your attempt to solve it.

Here is my approach to achieve similar result:

struct Ax { int x; };

struct Ay { int y; };

template <int I>
struct Aselector;

template<>
struct Aselector<0>{
    using type = Ax;
};

template<>
struct Aselector<1>{
    using type = Ay;
};

template<>
struct Aselector<2>{
    using type = Ax;
};

template <int I>
using A = typename Aselector<I>::type;

https://godbolt.org/z/fGxcoE5xd

Version using type traits is shorter:

#include <type_traits>

struct Ax { int x; };

struct Ay { int y; };

template <int I>
using A = std::conditional_t<I == 1, Ay, std::enable_if_t<I >= 0 && I <= 2, Ax>>;

https://godbolt.org/z/vMqPahfEo

CodePudding user response:

more complex situation, where for a set of values you have a specialization, for another set of values another specialization, etc...

A level of indirection can help here.

#include <iostream>
#include <type_traits>

template <size_t I> struct selector { static const size_t value = I; };    
template <> struct selector<2> { static const size_t value = 0;};
    
template <size_t J> struct Foo_impl { int x; };
template <> struct Foo_impl<1> { int y; };

template <size_t I> using Foo = Foo_impl< selector<I>::value >;
    
int main() {
    std::cout << std::is_same_v< Foo<0> , Foo<2> > << "\n";
    
    Foo<0> f0;
    f0.x = 42;
    Foo<1> f1;
    f1.y = 0;
    Foo<2> f2;
    f2.x = 123;
}

Foo<0> and Foo<2> are the same type. You can add more specializations to Foo_impl and you can add more mapping between the template argument I and actual index of specialization J.

CodePudding user response:

The other answers should work, I just wanted to offer a SFINAE based solution:

#include <iostream>

template <int I, typename = void>
struct A;

template <int I>
struct A<I, std::enable_if_t<I == 0 || I == 2>> { int x; };

template <typename Conditional>
struct A<1, Conditional> { int y; };

int main()
{
    std::cout << A<0>{}.x << std::endl;
    std::cout << A<1>{}.y << std::endl;
    std::cout << A<2>{}.x << std::endl;


    return 0;
}

Caveat: while this code allows A<0> and A<2> to share an implementation, they will not be identical types. Eg: std::is_same_v<A<0>, A<2>> will return true for the other answers, but false for this one.

  • Related