2

私は持っている:

class C 
{
    C(long){...};
    C(double){...};
    :
}

不運にも、

C c{5}; // error! ambiguous overload

(これはかなり恐ろしいことではありませんか? 整数型は、より高い精度の整数引数を取るコンストラクターを確実に優先する必要があります。)

整数引数と浮動小数点引数をそれぞれのコンストラクターに正しく転送するにはどうすればよいですか?

編集:質問を単純化しすぎたのかもしれません。もともとはこの問い合わせから来ています。Float Long String などの Python プリミティブをラップしています。初期化が正しいプリミティブに転送されることが重要です。同時に、これは汎用ラッパーであることを意図しているため、消費者が内部の落とし穴を避けるために型キャストについて心配する必要はありません。

Mike Seymour が指摘するように、SFINAE はこれを処理するテクニックを提供します。

以下のソリューションについて、FreeNode C++ チャネルの doug64k に大いに感謝します。

http://ideone.com/QLUpu2 http://ideone.com/TCigR3 http://ideone.com/oDOSLH

明日トレイルを拾うときに、これらを答えに変えようとします。

4

3 に答える 3

3

整数引数と浮動小数点引数をそれぞれのコンストラクターに正しく転送するにはどうすればよいですか?

使用する:

C c1{5L};
C c2{5.0};

これはかなり恐ろしいことですよね?整数型は、より高い精度の整数引数を取るコンストラクターを確実に優先する必要があります

標準では、最適なオーバーロード関数を決定するアルゴリズムに従います。とりわけ、「コンバージョン」よりも「プロモーション」が上位にランク付けされます。つまり、「積分昇格」は「積分変換」よりも上位にランクされ、「浮動小数点昇格」は「浮動小数点変換」よりも上位にランクされます。ただし、「整数変換」は「浮動小数点変換」より上位にはランク付けされません。セクション13.3.3.1.1 標準変換シーケンスの表を次に示します。

ここに画像の説明を入力

「整数昇格」、「整数変換」、「浮動小数点昇格」、および「浮動小数点変換」がセクション4 標準変換で使用できる標準アドレス。この回答の目的上、 anをnot Promoterに変換intできると言えば十分です。は に変換することもできます。これは、引数の型が.long intdoubleint

于 2014-12-03T16:09:27.250 に答える
2

私はそれをそのままにしておき、どの型変換が必要かについてユーザーに明示的に残します。記述した非標準ルールに従って暗黙的な変換を本当に許可したい場合は、SFINAE を使用できます。次のようなものが機能します。

#include <iostream>
#include <type_traits>

struct C {
    // Constructor for integer types
    template <typename T>
    C(T, typename std::enable_if<std::is_integral<T>::value, T>::type=0)
        {std::cout << "integral\n";}

    // Constructor for floating-point types
    template <typename T>
    C(T, typename std::enable_if<std::is_floating_point<T>::value, T>::type=0)
        {std::cout << "floating\n";}
};

int main() {
    C c1{5};   // prints "integral"
    C c2{5.0}; // prints "floating"
}

この意味不明なこと、および通常の暗黙の変換規則に慣れている人々の混乱が、明示的な変換で節約する価値があるかどうかは、意見の問題です。

于 2014-12-03T16:49:32.267 に答える
1

テンプレートコンストラクターを実行して、宣言されていない型を選択したコンストラクターにリダイレクトできます。

longあなたがデフォルトになりたいとしましょう。SFINAE を使用すると、型Tを としてキャストできるかどうかを確認longしてから、長いコンストラクターに渡すことができます!

class C 
{
public:
    C(long l){ std::cout << "long constructor" << std::endl; };
    C(double d){std::cout << "double constructor" << std::endl; };

    // default constructor which passes values to long
    template <typename T, 
       typename std::enable_if<std::is_convertible<long, T>::value, int>::type = 0>
    C(T t) : C(long(t)){};
};


int main() {
    C c1(5);
    C c2(5.0f);
    C c3(5.0L);
    C c4(5.0);
    return 0;
}

これは以下を出力します:

long constructor
long constructor
long constructor
double constructor
于 2014-12-03T16:51:36.970 に答える