基于整数范围的模板类中模板方法的特化

时间:2014-04-04 11:02:50

标签: c++ template-specialization

有没有办法在整数模板类中对模板函数进行范围特化?经过大量的研究后,我感觉答案可能只是简单而不是#34;但也许有一个巧妙的技巧或解决方法。

我尽可能地简化了我的课程来证明这个问题。

template<int value>
class MyClass
{
    template <typename T, typename X>
    uint64_t foo()
    {
        static_assert(sizeof(T) == 0, "Unsupported type combination.");
        return 0;
    }

    uint64_t m_member;
};

到目前为止很容易。非专用实现使用静态断言,因为我只希望模板函数用于某些类型。这些函数在类定义之外是专门的。

template<>
template<>
uint64_t MyClass<1>::foo<uint8_t, uint16_t>()
{
    return m_member * 1000;
}

template<>
template<>
uint64_t MyClass<7>::foo<uint8_t, uint16_t>()
{
    return m_member * 7000;
}

不,我正在寻找一种解决方案,将此专业化用于特定范围的val。我想要MyClass&lt; 0&gt;抛出静态断言,MyClass&lt; 1&gt;,MyClass&lt; 2&gt;,...,MyClass&lt; 6&gt;应该使用MyClass&lt; 1&gt;最后,MyClass&lt; 7&gt;必须使用第二个专业化。 foo 的其他专业不同。我有很多函数,比如 foo ,所有函数都有大约10种类型组合,并且它们的工作方式都非常不同。

最简单的解决方法是简单地复制专业化,但我希望有更好的解决方案。如果将 foo 保存为模板函数会很好,但我也可以使用定义 foo 的所有可能组合的解决方案,例如foo_u8_u16();, foo_u32_u64(),...

2 个答案:

答案 0 :(得分:0)

这应该有效:

template<int value, class T, class X>
struct Helper {
    static uint64_t foo(uint64_t param) {
        return Helper<value - 1, T, X>::foo(param);
    }
};

template<class T, class  X>
struct Helper<0, T, X> {
    static uint64_t foo(uint64_t param) {
        static_assert(sizeof(T) == 0, "Unsupported type combination.");
        return 0;
    }
};

template<>
uint64_t Helper<1, uint8_t, uint16_t>::foo(uint64_t param) {
    return param * 1000;
}

template<>
uint64_t Helper<7, uint8_t, uint16_t>::foo(uint64_t param) {
    return param * 7000;
}

template<int value>
class MyClass {
    template<class T, class X>
    uint64_t foo() {
        return Helper<value, T, X>::foo(m_member);
    }

    uint64_t m_member;
};

答案 1 :(得分:0)

你可以这样做:

#include <type_traits>

// the implementation of foo is moved to a different class

template<int value, typename = void>
struct FooImpl
{
    template <typename T, typename X>
    uint64_t foo()
    {
        static_assert(sizeof(T) == 0, "Unsupported type combination.");
        return 0;
    }
};

// partial specialization that will be enabled
// when value is in range [1,6)

template<int value>
    typename =  typename std::enable_if<value > 0 && value < 7>::type>
struct FooImpl<value,
        typename std::enable_if<(value > 0 && value < 7)>::type>
{
    template <typename T, typename X>
    uint64_t foo()
    {
        return 1000;
    }
    // you can write several overloads instead of a template, too
};

// now inherit from FooImpl

template<int value>
class MyClass : private FoomImpl<value>
{
    // write a forwarding function for foo here
    // or just a using declaration
};

希望这有助于我理解你的问题。