10

単純なtemplate <typename T> struct X { T x, y; };ものとして、ユーザーが次のように記述できるような変換コンストラクターを提供したいと思います。

X<double> a;
X<int16_t> b = a; // uses implicit conversion ctr (compiles with warning)
X<int16_t> c(a);  // uses explicit conversion ctr (compiles w/o warning)
X<int32_t> d = c; // uses implicit conversion ctr (compiles w/o warning)

この目標を達成するには、型からの暗黙的および明示的な変換コンストラクターの両方を実装する必要があると思いますU。ただし、「暗黙的」でオーバーロードすることはできませんexplicit

template <typename T> struct X {
     X(T x = T(), T y = T()) : x(x), y(y) {}

     // implicit conversion
     template <typename U> 
     X(const X<U>& other) : x(other.x), y(other.y) {}

     // not possible!
     template <typename U> 
     explicit X(const X<U>& other)
         : x(static_cast<T>(other.x))
         , y(static_cast<T>(other.y)) 
     {}

     T x, y;
};

どうすればこの目標を達成できますか(私はできないと思います...)?

私の最初の考えは、に応じてどちらかを有効/無効にする必要があるということでしたis_lossless_convertible。それで、適切なタイプの特性はありますか?

スカラー型が精度を失うことなくU型に変換できるかどうかをテストしたいと思います。T

using namespace std;
static_assert(is_lossless_convertible<int16_t, int32_t>::value == true);
static_assert(is_lossless_convertible<int32_t, int16_t>::value == false);
static_assert(is_lossless_convertible<int16_t, uint32_t>::value == false);
static_assert(is_lossless_convertible<int32_t, double>::value == true);
static_assert(is_lossless_convertible<double, int32_t>::value == false);

つまり、情報の損失に関するコンパイラ警告を発行するかtrueどうかstd::is_convertible<U, T>::value == true 、また発行しないかどうかを判断する必要があります。U x; T y = x;

4

1 に答える 1

6

明示性をオーバーロードすることはできませんが、明示的な変換コンストラクターと暗黙的な変換演算子を提供できます。

#include <iostream>
template<typename T> struct S {
   S() {}
   template<typename U> explicit S(const S<U> &) { std::cout << "explicit\n"; }
   template<typename U> operator S<U>() { return S<U>(this); }
private:
   template<typename U> friend struct S;
   template<typename U> S(const S<U> *) { std::cout << "implicit\n"; }
};

int main() {
   S<double> sd;
   S<int> si1(sd);
   S<int> si2 = sd;
}

出力:

explicit
implicit

gccとclangでテスト済み。

明示的な変換コンストラクターは、暗黙的な変換演算子よりも優先されます。後者の場合、のコピーコンストラクターへの追加の(場合によっては省略された)呼び出しがあるためですS<int>

于 2012-12-13T10:00:09.763 に答える