1

私が書いているプログラムでいくつかの不可解な SFINAE 問題が発生していたので、それを独立したサンプル プログラムにまとめました。

#include <type_traits>

struct Base { };

struct Derived : public Base { };

template<typename T>
struct From { };

template<typename T>
struct To {
    template<typename U>
    To(const From<U>& other) {
        static_assert(std::is_convertible<U*, T*>::value, "error");
    }
};

int main() {
    From<Derived> a;

    To<Base> b = a;
}

このプログラムは、エラーや警告なしでコンパイルされます。ただし、これは次のとおりです。

#include <type_traits>

struct Base { };

struct Derived : public Base { };

template<typename T>
struct From { };

template<typename T>
struct To {
    template<typename U>
    To(const From<typename std::enable_if<true, U>::type>& other) {
    // this       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        static_assert(std::is_convertible<U*, T*>::value, "error");
    }
};

int main() {
    From<Derived> a;

    To<Base> b = a;
}

次のエラーが発生します。

test.cpp: 関数内int main():

test.cpp:22:18: エラー: からFrom<Base>非スカラー型への変換がTo<Derived>要求されました

これは、おそらく置換が失敗し、コンストラクターが表示されないためです。

SFINAE のやり方が間違っているのでしょうか、それともコンパイラのバグですか? WindowsでruvenvbのGCC 4.7.1を使用しています(std=c++11違いがある場合)。

4

1 に答える 1

3

引数を推測できるように、デフォルトのテンプレート引数を使用します。

#include <type_traits>

struct Base { };

struct Derived : public Base { };

template<typename T>
struct From { };

template<typename T>
struct To {
    template<typename U, class = typename std::enable_if<true, U>::type>
    To(const From<U>& other) {
    // this       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        static_assert(std::is_convertible<U*, T*>::value, "error");
    }
};

int main() {
    From<Base> a;

    To<Derived> b = a;
}

static_assert逆に使用しているため、失敗することに注意してくださいstd::is_convertible。そのはず:

static_assert(std::is_convertible<T*, U*>::value, "error");

あなたの例では、テンプレートの種類Uを推測できません。other私のコードでは、コンストラクターの引数のテンプレート引数として使用されているため、推測できます。あなたのコードでは、コンパイラは a を見て、その型がstd::enable_if<true, U>::type何であるかを推測できません。Uその結果がenable_ifのテンプレート引数として使用されているという事実は、その前に推測する必要があるためFrom、まったく役に立ちません。U

于 2012-07-09T02:59:30.943 に答える