1 に答える
point
からへの変換を取得する直接的な方法はありません。これはvec<2>
、関数呼び出しfoo(v1,p1)
が処理される時点で、2 番目の引数としてfoo
を期待する関数vec<2>
がまだ存在しないためです。これは単なる関数テンプレートであり、これを にインスタンス化するにはfoo(const vec<2> &,const vec<2> &)
、これらの正確な引数型を使用した関数呼び出しを指定する必要があります。
コードが機能するために、コンパイラは、テンプレート パラメーターをインスタンス化する方法と、変換する引数の型の両方を推測する必要があります。これは一般的なケースでは多すぎます (ただし、プログラマーの意図を解釈する方法が他にないため、特定のコードでは単純に見えます)。point
これを解決するために、私が考えることができる唯一のことは、高度にテンプレート化された変換関数を作成することです。
template <typename T>
struct make_vec
{ };
template <unsigned d>
struct make_vec<vec<d>>
{
static constexpr unsigned dim = d;
using type = vec<dim>;
static const type &from(const type &v)
{ return v; }
};
template <>
struct make_vec<point>
{
static constexpr unsigned dim = 2;
using type = vec<dim>;
static type from(const point &p)
{ return type(p); }
};
template <typename T>
typename make_vec<typename std::decay<T>::type>::type make_vec_from(T&& arg)
{ return make_vec<typename std::decay<T>::type>::from(std::forward<T>(arg)); }
そして、foo
およびbar
関数を一般的なテンプレートとして実装します ( だけでなく、すべての種類の型を受け入れ、上記で定義したものをvec<d>
使用しmake_vec
て、指定された型を正しい種類の に変換しますvec<d>
)。
namespace detail {
/* Your original implementation of foo. */
template<unsigned d> vec<d> foo(vec<d>, vec<d>) {
return vec<d>(/* ... */);
}
}
/* Templated version of foo that calls the conversion functions (which do
nothing if the argument is already a vec<d>), and then calls the
foo() function defined above. */
template <typename T, typename... Ts>
typename make_vec<typename std::decay<T>::type>::type foo(T&& arg, Ts&&... args)
{ return detail::foo(make_vec_from(arg),make_vec_from(args)...); }
の場合bar
、戻り値の型を計算する方法も必要ですvec<d1+d2+d3...>
。このためには、同じくテンプレート化された合計計算機が必要です。
template <typename... Ts>
struct dsum {
static constexpr unsigned value = 0;
};
template <typename T, typename... Ts>
struct dsum<T,Ts...> {
static constexpr unsigned value = make_vec<typename std::decay<T>::type>::dim + dsum<Ts...>::value;
};
次に、 の戻り値の型はbar()
ですvec<dsum<T,Ts...>::value>
。
完全に機能する例は次のとおりです: http://liveworkspace.org/code/nZJYu$11
厳密には単純ではありませんが、非常に多くの異なる引数の組み合わせがある場合は、価値があるかもしれません。