Lorenzo Pistone
Lorenzo Pistone

Reputation: 5188

template argument involving template parameters

Is there a way to workaround the limitations of the standard when it comes to use template parameters in template arguments in partial specialization? The code that I'd like to make it work is this:

template<typename L, size_t offset, typename enable_if< (offset<sizeof(L)), int >::type =0>
class a{};

template<typename L>
class a<L, sizeof(L)-1>{};

Upvotes: 2

Views: 1520

Answers (2)

hansmaad
hansmaad

Reputation: 18905

I dont know if this is what you mean. This is how you can select a different implementation if the second template arguemnt matches the size of first template argument - 1.

template<typename L, size_t offset>
class aImplMatch
{   // choose this if offset == sizeof(L) - 1
    L v;
};

template<typename L, size_t offset>
class aImpl
{  
    L v;
    char off[offset];
};

template<typename L, size_t offset, size_t i>
struct SelectImpl{};

template<typename L, size_t offset>
struct SelectImpl<L, offset, 0> { typedef aImplMatch<L, offset> Result; };

template<typename L, size_t offset>
struct SelectImpl<L, offset, 1> { typedef aImpl<L, offset> Result; };

template<typename L, size_t offset>
class a
{
    enum {I = offset == sizeof(offset) - 1 ? 0 : 1 };
    typedef typename SelectImpl<L, offset, I>::Result Impl;
    Impl impl;
};

Maybe it could be done better / easier, this was my first thought...

Upvotes: 2

kennytm
kennytm

Reputation: 523174

Since it's C++11, you could simply use static_assert for the generic condition. For the sizeof(L)-1 thing, you need to use the enable_if trick since it requires something to be specialized. Example:

#include <cstdlib>
#include <type_traits>
#include <cstdio>

template <typename L, size_t offset, typename = void>
class a
{
    static_assert(offset < sizeof(L), "something's wrong");
public:
    void f()
    {
        printf("generic\n");
    }
};

template <typename L, size_t offset>
class a<L, offset, typename std::enable_if<offset == sizeof(L)-1>::type>
{
    // note: the static_assert is *not* inherited here.
public:
    void f()
    {
        printf("specialized\n");
    }
};

int main()
{
    static_assert(sizeof(int) == 4, "oops");
    a<int, 3> x;
    a<int, 2> y;
    x.f();
    y.f();
    return 0;
}

Demo: http://ideone.com/D2cs5

Upvotes: 5

Related Questions