【问题标题】:Template specialization for multiple types多种类型的模板特化
【发布时间】:2013-07-11 17:29:56
【问题描述】:

标题有点模糊。

假设我有一个模板定义为:

template < typename T >
void foo ( int x ) ;
template <>
void foo<char> ( int x ) ;
template <>
void foo<unsigned char> ( int x ) ;
template <>
void foo<short> ( int x ) ;
...

在内部,foo&lt;signed&gt;()foo&lt;unsigned&gt;() 都做同样的事情。唯一的要求是T 是 8 位类型。

我可以通过创建另一个模板来键入基于大小定义标准类型来做到这一点。

template < typename T, size_t N = sizeof( T ) > struct remap ;
template < typename T, size_t > struct remap< 1 >
{
    typedef unsigned char value;
}
...

注意,函数模板不能有默认参数。此解决方案只会将问题重新定位到另一个模板,如果有人尝试将结构类型作为参数传递,也会引入问题。

在不重复这些函数声明的情况下解决这个问题的最优雅的方法是什么?

这不是 C++11 问题。

【问题讨论】:

  • 您是否尝试过使用 enable_if 来检查类型的大小?我假设你对所有相同大小的内置类型都做同样的事情?
  • @Borgleader enable_if 是 C++11
  • SFINAE 和 enable_if 也可以在 C++03 中实现。
  • @DyP 我无法访问完整的 C++11,所以我从未使用过 enable_if。它将如何解决这个问题?
  • 如果我理解正确,您希望避免代码重复。我看到的最简单的方法是从foo&lt;signed&gt;foo&lt;unsigned&gt; 内部调用相同的函数。还有其他类似于您的remap 建议的方法,但我认为您最终会使用更多代码来避免重复。

标签: c++ templates c++03


【解决方案1】:

一种可能性是一次为多种类型专门化一个类模板:

// from: http://en.cppreference.com/w/cpp/types/enable_if
    template<bool B, class T = void>
    struct enable_if {};

    template<class T>
    struct enable_if<true, T> { typedef T type; };

template < typename A, typename B >
struct is_same
{
    static const bool value = false;
};
template < typename A >
struct is_same<A, A>
{
    static const bool value = true;
};


template < typename T, typename dummy = T >
struct remap;

template < typename T >
struct remap
<
    T,
    typename enable_if<    is_same<T, unsigned char>::value
                        || is_same<T, signed char>::value, T >::type
>
{
    void foo(int);
};


int main()
{
    remap<signed char> s;
    s.foo(42);
}

另一种可能性是为类型的类别(类型特征)专门化一个类模板:

#include <cstddef>

template < typename T >
struct is_integer
{
    static const bool value = false;
};
template<> struct is_integer<signed char> { static const bool value = true; };
template<> struct is_integer<unsigned char> { static const bool value = true; };


template < typename T, typename dummy = T, std::size_t S = sizeof(T) >
struct remap;

template < typename T >
struct remap
<
    T
    , typename enable_if<is_integer<T>::value, T>::type
    , 1 // assuming your byte has 8 bits
>
{
    void foo(int);
};


int main()
{
    remap<signed char> s;
    s.foo(42);
}

【讨论】:

  • 我只是想指出有一个 std::enable_if,所以你不必自己定义它。见here
  • @leetNightshade enable_if 已在 C++11 中添加;该问题针对 C++03(另外,我已经使用相同的链接向 OP 添加了评论;)
【解决方案2】:

您需要您的 remap trait 来简单地从输入类型映射到输出类型,并将您的 foo&lt;T&gt;(int) 接口函数委托给 foo_implementation&lt;remap&lt;T&gt;::type&gt;(int) 实现。即:

template <typename T>
struct remap {
    // Default: Output type is the same as input type.
    typedef T type;
};

template <>
struct remap<char> {
    typedef unsigned char type;
};

template <>
struct remap<signed char> {
    typedef unsigned char type;
};

template <typename T>
void foo_impl(int x);

template <>
void foo_impl<unsigned char>(int x) {
    std::cout << "foo_impl<unsigned char>(" << x << ") called\n";
}

template <typename T>
void foo(int x) {
    foo_impl<typename remap<T>::type>(x);
}

See it live at ideone.com.

也就是说,定义foo_charfoo_intfoo_short 并从客户端代码中调用正确的可能实际上更简单。 foo&lt;X&gt;() 在语法上与 foo_X() 没有太大区别。

【讨论】:

    猜你喜欢
    • 2019-08-20
    • 2017-09-20
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多