【问题标题】:Integer range based specialization of template method in template class模板类中模板方法的基于整数范围的特化
【发布时间】:2014-04-04 11:02:50
【问题描述】:

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

我尽可能简化我的课程来演示问题。

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 抛出静态断言, MyClass, MyClass, ... , MyClass 应该使用 MyClass 最后 MyClass 必须使用第二个专业化。 foo 的其他特化工作不同。我有很多像 foo 这样的函数,并且都有大约 10 种类型组合在工作,而且它们的工作方式都非常不同。

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

【问题讨论】:

  • 你能再解释一下吗?像MyClass&lt;1&gt;::foo&lt;int, double&gt;(); 这样的东西呢?您是否打算将MyClass 的某些专业化限制为仅foo 的一个专业化?
  • 我确实需要像 MyClass::foo(); 这样的东西。对单一专业化的限制意味着我根本不需要模板类函数。
  • 那我不明白你为什么在你的例子中明确专门化foo。所以,为了确认一下,MyClass&lt;7&gt;::foo&lt;uint8_t, uint16_t&gt;();MyClass&lt;7&gt;::foo&lt;int, double&gt;() 应该做同样的事情吗?
  • 你的问题很有道理。我编辑了问题以使其更清楚。如果允许,这两个专业会做不同的事情。如果 foo 是否是模板函数,可能的解决方案可能并不重要。关键是整数范围的函数特化。

标签: c++ template-specialization


【解决方案1】:

这应该可行:

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;
};

【讨论】:

  • 我刚刚编辑了问题并添加了成员​​值。这可以简单地作为参数传递给静态版本的 foo。总而言之,这个解决方案看起来很有前途。我会试试看。
  • 是的,这是一个微不足道的变化。我更新了答案的完整性。
  • 对我来说很好。感谢您的帮助!
【解决方案2】:

你可以这样做:

#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
};

希望对您有所帮助,并且我正确理解了您的问题。

【讨论】:

    猜你喜欢
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-15
    • 2021-04-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多