質問
Visual Studio 10(ベータ2)を試している間にいくつかの簡単なポイントコードを書いています。SFINAEが作動するはずのこのコードにヒットしましたが、そうではないようです:
template<typename T>
struct point {
T x, y;
point(T x, T y) : x(x), y(y) {}
};
template<typename T, typename U>
struct op_div {
typedef decltype(T() / U()) type;
};
template<typename T, typename U>
point<typename op_div<T, U>::type>
operator/(point<T> const& l, point<U> const& r) {
return point<typename op_div<T, U>::type>(l.x / r.x, l.y / r.y);
}
template<typename T, typename U>
point<typename op_div<T, U>::type>
operator/(point<T> const& l, U const& r) {
return point<typename op_div<T, U>::type>(l.x / r, l.y / r);
}
int main() {
point<int>(0, 1) / point<float>(2, 3);
}
これによりerror C2512: 'point<T>::point' : no appropriate default constructor available
ベータ版であることを考えると、私はオンラインコモーコンパイラで簡単な健全性チェックを行い、同じエラーと一致するため、この動作は正しいようですが、理由はわかりません。
この場合、いくつかの回避策は、単にdecltype(T() / U())
をインライン化するか、ポイントクラスにデフォルトコンストラクターを与えるか、完全な結果式でdecltypeを使用することですが、エラーを単純化しようとしてこのエラーが発生しましたデフォルトのコンストラクター*を必要としないバージョンのop_divを使用しているため、動作するだけでなくC ++の理解を修正したい。
ありがとう!
*:オリジナル:
template<typename T, typename U>
struct op_div {
static T t(); static U u();
typedef decltype(t() / u()) type;
};
error C2784: 'point<op_div<T,U>::type> operator /(const point<T> &,const U &)' : could not deduce template argument for 'const point<T> &' from 'int'
を与えるもの、およびpoint<T> / point<U>
オーバーロードを与えるもの。
解決
100%確実ではありません。どちらの方が良いかを判断するには、コンパイラーが両方のオーバーロードをインスタンス化する必要があるようですが、他のop_divをT = int
とU = point<float>
でインスタンス化しようとすると、SFINAEでカバーされないエラーが発生します(エラーはこの場合、op_divにはタイプはありませんが、そのタイプを判別することはできません)。
2番目のタイプがポイント(boost::disable_if
)の場合、2番目のオーバーロードを無効にしようとすることができます。
また、動作するように思われるのは、戻り型の宣言を延期することです(op_div構造体は廃止しますが、コンパイラーがサポートしているC ++ 0x機能によって異なります):
template<typename T, typename U>
auto
operator/(point<T> const& l, point<U> const& r) -> point<decltype(l.x / r.x)> {
return {l.x / r.x, l.y / r.y};
}
template<typename T, typename U>
auto
operator/(point<T> const& l, U const& r) -> point<decltype(l.x / r)> {
return {l.x / r, l.y / r};
}
他のヒント
あなたのエラーはここにあると思います:
template<typename T>
struct point {
T x, y;
point(T x, T y) : x(x), y(y) {}
};
構造体の定義を次のように変更します。
template<typename T>
struct point<T> {
T x, y;
point(T x, T y) : x(x), y(y) {}
};
ジェネリック型Tを使用する場合は、定義で指定する必要があります。