1

I would like to specialized the behaviour of a template function member according to the enum member of the class it is operating on. I am pretty sure this is doable but I can't see how. Here is a failed attempt which doesn't compile (why ?). In fact I already got a working solution for my project (using inheritance) but this isn't nice and I am curious about what could be done.

#include <iostream>

struct A
{
    enum
    {
        Size = 2    
    };
};

struct B
{
    enum
    {
        Size = 3
    };
};

template <int I>
struct EnumToType
{
    static const int e = I;
};

template <typename T, typename U>
struct C {};

template <typename T>
struct D
{
    typedef C<T, typename EnumToType<T::Size> > Type;
};

template <typename T>
struct C<T, EnumToType<2> >
{
    void operator()()
    {
        std::cout << "hi !" << std::endl;
    }    
};

template <typename T>
struct C<T, EnumToType<3> >
{
    void operator()()
    {
        std::cout << "hello !" << std::endl;
    }    
};

int main()
{
    D<A>::Type da;
    D<B>::Type db;
    da();
    db();
    return 0;
}

A useful link...

Community
  • 1
  • 1
matovitch
  • 1,264
  • 11
  • 26

3 Answers3

2
typedef C<T, typename EnumToType<T::Size> > Type;

The typename keyword here is meaningless and illegal, just remove it.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • I removed it and it worked. Thanks ! Are there a better c++03 way to achieve what I want though ? – matovitch May 22 '14 at 18:44
  • I don't see why you need EnumToType at all, might just use the values directly. Other than that, no, I don't see anything bad here. – n. m. could be an AI May 22 '14 at 18:50
  • It worked again ! I thought it wouldn't work because of the link I gave at the end (as well as the link given by Constructor) but this pseudo-template-typedef isn't partial template specialization (apparently) so it work. :-) – matovitch May 22 '14 at 18:55
1

The general pattern looks as follows (using a bool instead of an enum type, but the principle stays the same):

template<typename FalseType, typename TrueType, bool condition> 
struct ConditionalTypeSelector {
    typedef void ResultType;
};

template<typename FalseType, typename TrueType>
struct ConditionalTypeSelector<FalseType,TrueType,false> {
    typedef FalseType ResultType;
};

template<typename FalseType, typename TrueType>
struct ConditionalTypeSelector<FalseType,TrueType,true> {
    typedef TrueType ResultType;
};

Use it somewhere else

ConditionalTypeSelector<A,B,(sizeof(A) > sizeof(B))>::ResultType
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • I appreciate the time you take to answer my question but this isn't the same pattern. Your example is just template specialization, the condition doesn't depend on A or B static const member...or I am misunderstanding something. – matovitch May 22 '14 at 19:05
  • @matovitch I've taken this sample quickly from a [blog entry](http://dev-jungle.blogspot.de/2014/02/conditional-type-selection-using-c.html) of mine. The `ConditionalTypeSelector` class could be easily use your proposed enum type instead of `bool` condition, and have more specializations for the enum values of course. I still think it's the same pattern. – πάντα ῥεῖ May 22 '14 at 19:10
1

I have to question what it is you are trying to achieve, but here is one way of solving your example:

struct A
{
    static const int Size = 2;
};

struct B
{
    static const int Size = 3;
};

template<int message_id>
struct Message;

template<>
struct Message<2>
{
    void operator()()
    {
        std::cout << "hi !" << std::endl;
    }    
};

template<>
struct Message<3>
{
    void operator()()
    {
        std::cout << "hello !" << std::endl;
    }
};

template<typename T>
struct SizeStructToMessage
{
    void operator()()
    {
        Message<T::Size> msg;
        msg();
    }
};

int main()
{
    SizeStructToMessage<A> a;
    SizeStructToMessage<B> b;
    a();
    b();
    return 0;
}
  • Yes, it's that same pattern. Doesn't matter if you have a call operator, `typedef` or whatever. In case of the op's question he want's to do this with an enumeration not an `int`, but it pretty much boils down to the same thing. – πάντα ῥεῖ May 22 '14 at 20:15
  • @Curg I am implementing a library for discrete wavelet transform using lifting scheme. I especially use template for loops unrolling. In this case, I wanted to implement ApplyForward and ApplyReverse functors which shouldn't exhibit the same behaviour if the lifting to apply is primal or dual (since I am using traits classes, using inheritance means moving them back up alias more boiler-plate :/). – matovitch May 22 '14 at 22:34