3

**関数を純粋汎用にするためのいくつかの提案がありますが、これは機能しますが、Baseとその子のみを受け入れるように関数を制限したいと思います。

可変個引数テンプレートクラスの基本型の引数を受け入れることができる関数を作成するのに問題がありますが、関数は実際にはBaseから派生したクラスで呼び出されます。私はいくつかのことを試しました。これが一般的な考え方です。与えられた:

template<typename... Args> struct Base {
    std::tuple<Args...> data;
    ... //other stuff
};

struct DerivedA : Base<string, int> {
};

struct DerviedB : Base<bool, string, int> {
};

これを行う関数を作成する正しい方法は何ですか?

string moosh_together(Base A, Base B) { //I only need access to Base's members
    return get<0>(A.data) + get<1>(B.data);
}

main() {
    DerivedA aThing;
        get<0>(aThing.data) = "foo";
    DerivedB bThing;
        get<1>(bThing.data) = "bar'd";
    cout << moosh_together(aThing, bThing) << endl;
}

出力:

foobar'd

moosh_together関数のいくつかのバリエーションを試しましたが、どれも機能しません。上記のままにしておくと、テンプレート引数の欠落に関するコンパイラエラーが発生します。DerivedAとDerivedBを定義するテンプレート引数を関数に渡す方法がわかりません。

私が試した他のこと(ショットガン法):

string moosh_together(Base<> A, Base<> B) {}
//err: conversion from 'DerivedA' to non-scalar type 'Base<>' requested

template<Base<typename... Args> T1, Base<typename... Args> T2>
string moosh_together(T1 A, T2 B) {}
//err: expected paramter pack before '...'

template<Base<Args...> T1, Base<Args...> T2>
string moosh_together(T1 A, T2 B) {}
//err: 'Args' was not declared in this scope
4

4 に答える 4

4

編集:

両方のパラメーター パックが必要な場合は、両方をテンプレート仕様に入れるだけです。

template<typename... ArgsA, typename... ArgsB>
string moosh_together(const Base<ArgsA...>& A, const Base<ArgsB...>& B) {
    return get<0>(A.data) + get<1>(B.data);
}

これが機能するのは、パラメーター パックが引数から推測され、リストで指定されていないためです。当然、複数のパラメーター パックに依存するクラスを持つことはできません。

于 2010-09-08T19:43:29.870 に答える
2

あなたが書くとき:string moosh_together(Base A, Base B)、何であるかを自問してくださいBaseBaseクラステンプレートであり、クラスタイプではありません。

言い換えれば、与えられた:

template <typename T>
struct foo {};

foo<int>foo<float>はまったく異なる2つのタイプであり、たまたま同じクラステンプレートから作成されたものです。それらには共通の基本クラスがなく、両方と単一のタイプでfoo参照できる以上に、単純にそれらを参照することはできません。intfloat

の非依存部分を除外することができますBase

struct Core
{
    string name;
};

template <typename... Args>
struct Base : Core
{
    // ...
};

そして、そのCore部分を参照してください。

// pass by reference, to avoid unnecessary copying
string moosh_together(const Core& a, const Core& b);

または、関数を完全に汎用的にします。

template <typename BaseOne, typename BaseTwo>
string moosh_together(const BaseOne& a, const BaseTwo& b);

そして、「必要なメンバーがいれば、この機能を利用できます」と言ってください。

于 2010-09-08T19:40:02.613 に答える
1

これの一般的な展開は

string moosh_together(Base<T1...> A1, Base<T2...> A2, ... Base<Tn...> An) {
    return get<0>(A1.data) + get<1>(A2) + ... + get<n-1>(An.data);
}

これは次のように書ける

template<int I> 
string moosh_together() { return ""; }

template<int I, typename ...Base1Ty, typename ... Bases>
string moosh_together(Base<Base1Ty...> const& base1, Bases const&... bases) {
    return get<I>(base1.data) + moosh_together<I+1>(bases...); 
}

template<typename ... Bases>
string moosh_together(Bases const&... bases) {
    return moosh_together<0>(bases...);
}
于 2010-09-08T20:45:53.910 に答える
1

の継承階層に基底クラスを作成し、それを関数Baseに渡すことはできませんか? moosh_together()(ここではC ++の知識が低い)

于 2010-09-08T19:26:21.937 に答える