2

まず、英語で大きな間違いを犯したらごめんなさい。私はフランス語ですが、できる限り最善を尽くして書いています。さて、私は C++11 可変個引数テンプレートに苦労しています。ちょっとややこしいことをしたい。

確かに、テンプレートが可変個引数テンプレートであることを知って、テンプレートの戻り値の型を特殊化したいと考えています。

私の目標は、次のようなものを達成することです:

l.callFun<int>("addition", 40, 1, 1);

特殊化は、ユーザーが必要とする戻り値の型に対応しています。これは Lua バインディングであるため、ユーザーが正確に指定しないと、戻り値の型を特定できません (明らかに、特殊化されていない場合のデフォルトは void 戻り値になります)。あと、Luaで呼ばれる関数の名前です。次に、3 つの整数が可変個引数テンプレートに対応します。

現在、私のテンプレートは次のようになっています。

template <typename Z, typename T, typename... U>
Z LuaScript::callFun(const std::string& name, const T& head, const U&... tail);

しかし、テンプレート関数の部分的な特殊化はできないようです。私を助けてくれる人はいますか?

どうもありがとうございました!

4

3 に答える 3

1

Perfect forwarding the initial call to a helper class member function should facilitate what you want.

template<typename Z>
struct callFun_helper {
    template<typename T, typename... U>
    static Z help(const std::string& name, const T& head, const U&... tail) {
        Z thing;
        //do something with "thing"
        return thing;
    }
};

template<typename Z, typename S, typename T, typename... U>
auto callFun(S&& s, T&& t, U&&... u)
-> decltype(callFun_helper<Z>::help(std::forward<S>(s), std::forward<T>(t), std::forward<U>(u)...)) {
    return callFun_helper<Z>::help(std::forward<S>(s), std::forward<T>(t), std::forward<U>(u)...);
}

//main
callFun<string>("addition", 40, 1, 1)    

The link below might help you with partial template specialization if you want to know more about what you can/can't do with it. Also, don't forget to mark an answer if you want to continue getting answers in the future here at StackOverflow :)

Why Not Specialize Function Templates?

于 2013-05-31T19:58:58.413 に答える
1

インターフェイスを変更する必要のない解決策は、関数呼び出しを に転送するtemplate<> classことです。ここで、心のコンテンツに特化できます。

template<typename R, typename... Ts>
struct DoCallFun {
  R operator()( LuaScript* self, std::string const& name, Ts&&... ts ) {
  }
};

template <typename Z, typename... T>
Z LuaScript::callFun(const std::string& name, Ts&&... ts) {
  return DoCallFun<Z, Ts...>()( this, name, head, std::forward<Ts>(ts)... )
}

callFunそして、 withinの本体を実装しますDoCallFun。プライベート変数へのアクセスが必要な場合LuaScriptDoCallFunfriend.

現在、より良い解決策は、タイプ依存の動作classの多くに「特性」を使用することです。return型に基づいて異なる関数を呼び出す必要がある場合は、型ごとにわずかな違いでreturn同じものを 1 回記述するのではなく、型に基づいて違いを分離する "特性"を作成できます。callFunreturnclassreturn

int CallAndReturnInt(...)タイプが であり、タイプがintdouble CallAndReturnDouble(...)ある場合に呼び出す必要があるとしますdouble。の本体を 2 つ持つ代わりにcallFun、特性クラスを作成します。

template<typename T>
struct lua_return_traits;
template<>
struct lua_return_traits<int> {
  template<typename... Ts>
  static int call_and_return( Ts&&... ts ) {
    return CallAndReturnInt( std::forward<Ts>(ts) );
  }
};
template<>
struct lua_return_traits<double> {
  template<typename... Ts>
  static double call_and_return( Ts&&... ts ) {
    return CallAndReturnDouble( std::forward<Ts>(ts) );
  }
};

returnまた、タイプに基づいてメソッドが異なる必要がある他の方法についても同様の手法を使用します。

于 2013-06-01T09:47:02.713 に答える
1

ヘルプとドキュメンテーションは pheedbaq に非常に感謝していますが、最終的には本当に簡単な解決策にたどり着きました。私はそのように考えていませんでしたので、あなたのおかげで演算子のオーバーロードのこの方法を試してみます ;)

私が行ったことは、可変引数をパックし、別のテンプレートを呼び出して戻り値の型に特化することです。だから私はそのようなものを持っています:

template <typename Z, typename... T>
Z LuaScript::callFun(const std::string& name, const T&... args)
{
    Z ret;
    callFunReal(args);
    [...]
    ret = returnType<Z>();
    return (ret);
}

すごく簡単なのですが、やり方がよくわかりませんでした… 皆さん、ありがとうございました!:) </p>

于 2013-06-01T04:16:59.393 に答える