apramc
apramc

Reputation: 1386

custom template programming

I am trying to write a container class that changes behavior depending on the based on a given dimension of the class as follow:

template <typename T, size_t DIM>
class Container { ... };

I tried to achieve that by using type_triats as follow:

template<typename T, size_t DIM, typename ENABLE = typename std::enable_if<
        std::integral_constant<bool, DIM == 1>::value>::type>
{ // implementation for 1D };

and for 2 d container as follow:

template<typename T, size_t DIM, typename ENABLE = typename std::enable_if<
            std::integral_constant<bool, DIM == 2>::value>::type>
    { // implementation for 2D };

by I get redefenition error ?!

Any idea how I can implement this customization.

Also, is there anyway that I can mask the implementaion of method using enable_if ??!!!

Upvotes: 2

Views: 70

Answers (2)

Henri Menke
Henri Menke

Reputation: 10939

You can do this with SFINAE, but I don't see any reason to not just use explicit specialisation.

#include <iostream>
#include <type_traits>

// enable_if_t only available since C++14
#if ! ( __cplusplus > 201103L )
namespace std {
  template< bool B, class T = void >
  using enable_if_t = typename enable_if<B,T>::type;
}
#endif

template < typename T, size_t DIM, typename = void >
class Container
{
public:
  Container() { std::cout << "Hello from generic\n"; }
};

template < typename T, size_t DIM >
class Container < T, DIM, std::enable_if_t<DIM == 1> >
{
public:
  Container() { std::cout << "Hello from DIM = 1\n"; }
};

template < typename T, size_t DIM >
class Container < T, DIM, std::enable_if_t<DIM == 2> >
{
public:
  Container() { std::cout << "Hello from DIM = 2\n"; }
};

int main()
{
  Container<int, 1> c1;

  Container<int, 2> c2;

  Container<int, 3> c3;
}

Upvotes: 1

Kerrek SB
Kerrek SB

Reputation: 476940

That's not what enable_if is for. What you most likely want is a straight-up specialization:

template <typename, size_t> class Container;

template <typename T> class Container<T, 1> {
  // 1-D impl
};

template <typename T> class Container<T, 2> {
  // 2-D impl
};

// etc.

Common behaviour can be factored into base classes if needed.

Upvotes: 4

Related Questions