7

次の例を検討してください。

struct Scanner
{
    template <typename T>
    T get();
};

template <>
string Scanner::get()
{
    return string("string");
}

template <>
int Scanner::get()
{
    return 10;
}

int main()
{
    Scanner scanner;
    string s = scanner.get<string>();
    int i = scanner.get<int>();
}

このScannerクラスは、何らかのソースからトークンを抽出するために使用されます。上記のコードは問題なく動作しますが、 aや angetなどの他の整数型にしようとすると失敗します。これらの型を読み取るコードは、 を読み取るコードとまったく同じです。読みたい他のすべての整数型のコードを複製することもできますが、すべての整数型に対して 1 つの関数テンプレートを定義したいと思います。charunsigned intint

私は次のことを試しました:

struct Scanner
{
    template <typename T>
    typename enable_if<boost::is_integral<T>, T>::type get();
};

Scanner::get<string>()これは魅力のように機能しますが、再び機能する方法がわかりません。では、単一の定義ですべての整数型を読み取ることができるように、コードを作成するにはどうすればよいscanner.get<string>()でしょうか?scanner.get<any integral type>()

更新: おまけの質問: いくつかの特性に基づいて複数の範囲のクラスを受け入れたい場合はどうすればよいですか? たとえば、 get(i) 整数型 (ii) 浮動小数点型 (iii) 文字列をそれぞれ受け入れる 3 つの関数が必要な場合、この問題にどのようにアプローチすればよいでしょうか。

4

2 に答える 2

10
struct Scanner
{
    template <typename T>
    typename boost::enable_if<boost::is_integral<T>, T>::type get()
    {
        return 10;
    }
    template <typename T>
    typename boost::disable_if<boost::is_integral<T>, std::string>::type get()
    {
        return "string";
    }
};

「いくつかの特性に基づいて複数の範囲のクラスを受け入れたい場合はどうすればよいですか?」を更新します。

struct Scanner
{
    template <typename T>
    typename boost::enable_if<boost::is_integral<T>, T>::type get()
    {
        return 10;
    }

    template <typename T>
    typename boost::enable_if<boost::is_floating_point<T>, T>::type get()
    {
        return 11.5;
    }

    template <typename T>
    std::string get(
          typename boost::disable_if<boost::is_floating_point<T>, T>::type* = 0, 
          typename boost::disable_if<boost::is_integral<T>, T>::type* = 0)

    {
        return std::string("string");
    }
};
于 2010-03-29T10:57:14.097 に答える
3

別のテンプレートに従います。必要なものの一般的なパターンは次のとおりです。

template <typename T, bool HasTrait = false>
struct scanner_impl;

template <typename T>
struct scanner_impl
{
    // Implement as though the trait is false
};

template <typename T>
struct scanner_impl<true>
{
    // Implement as though the trait is true
};

// This is the one the user uses
template <typename T>
struct scanner : scanner_impl<T, typename has_my_trait<T>::value>
{
};
于 2010-03-29T10:53:34.233 に答える