14

タイトルは少しあいまいです。

次のように定義されたテンプレートがあるとします。

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<signed>()まったくfoo<unsigned>()同じことを行います。唯一の要件は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 に関する質問ではありません。

4

2 に答える 2

12

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

もう 1 つの可能性は、クラス テンプレートを型のカテゴリ (型特性) に特化することです。

#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);
}
于 2013-07-13T06:16:03.813 に答える
7

remap入力型から出力型に単純にマッピングし、foo<T>(int)インターフェイス関数を実装に委譲する特性が必要ですfoo_implementation<remap<T>::type>(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);
}

ideone.com でライブをご覧ください

foo_charとはいえ、foo_intを定義して、foo_shortクライアント コードから正しいものを呼び出す方が現実的には簡単かもしれません。foo<X>()と構文的に大差ありませんfoo_X()

于 2013-07-13T06:31:03.323 に答える