Home > Mobile >  How to specialize a value template with multiple enum values
How to specialize a value template with multiple enum values

Time:12-12

If I have the following code, which is a struct with value templates,

enum FakeEnum
{
    FakeNone,
    Fake1,
    Fake2,
    Fake3,
    Fake4,
    Fake5,
    Fake6,
    Fake7,
    Fake8,
    Fake9,
    Fake10,
    Fake11,
    Fake12,
    Fake13,
    Fake14,
    Fake15,
    Fake16,
    Fake17,

    // ...

    Fake100,
};

template<FakeEnum FE>
struct FakeStruct
{
    void FakeIt();
};

template<FakeEnum FE>
void FakeStruct<FE>::FakeIt()
{
    std::cout << "void FakeStruct<" << FE << ">::FakeIt()";
}

template<>
void FakeStruct<Fake12>::FakeIt()
{
    std::cout << "specialized on Fake12";
}

template<>
void FakeStruct<Fake14>::FakeIt()
{
    std::cout << "specialized on Fake14";
}

template<>
void FakeStruct<Fake23>::FakeIt()
{
    std::cout << "specialized on Fake23";
}

...

...but what I'd really like to write is something like

template<>
void FakeStruct<Fake12 || Fake13 || Fake14 or how do I do this???>::FakeIt()
{
    std::cout << "specialized on Fake12, Fake13, and Fake14";
}

Is there some kind of SFINAE-ish way to write that FakeStruct<>::FakeIt() specialization without repeating it for multiple enum values? Ideally without changing the original declaration/signature of FakeStruct?

CodePudding user response:

Use requires:

#include <iostream>

enum E {a, b, c, d};

template <E Value>
struct A
{
    void foo()
    {
        std::cout << "0\n";
    }
};

template <E Value> requires (Value == b || Value == c) // or `Value >= b && value <= c`
struct A<Value>
{
    void foo()
    {
        std::cout << "1\n";
    }
};

int main()
{
    A<a>{}.foo(); // 0
    A<b>{}.foo(); // 1
    A<c>{}.foo(); // 1
    A<d>{}.foo(); // 0
}

CodePudding user response:

I would use if constexpr, it is still meta template programming but looks a lot like normal c .

#include <type_traits>
#include <iostream>

enum class FakeEnum // <= don't forget class here
{
    FakeNone,
    Fake1,
    Fake2,
    Fake3,
    Fake4,
    Fake5
};

template<FakeEnum E>
void FakeIt()
{
    // you now can make sprecializations using "if constexpr"
    if constexpr ((E == FakeEnum::Fake2) || (E == FakeEnum::Fake3) || (E == FakeEnum::Fake4))
    {
        // functionality here or call another function if needed
        std::cout << "2 Or 3 Or 4\n";
    }
    else
    {
        std::cout << "1 or 5\n";
    }
}


int main()
{
    FakeIt<FakeEnum::Fake1>();
    FakeIt<FakeEnum::Fake5>();
    FakeIt<FakeEnum::Fake3>();
    
    return 0;
}
  • Related