0

私はエラーメッセージを改善するためにいくつかの賢明な静的アサーションの使用を調査してきました。次に例を示します。

#include <type_traits>
template<typename T> struct is_less_than_comparable {
    template<typename Test> static char test(decltype(*static_cast<Test*>(nullptr) < *static_cast<Test*>(nullptr)));
    template<typename Test> static int test(...);
    static const bool value = std::is_same<char, decltype(test<T>(true))>::value;
};
template<typename K, typename V> class map {
public:
    static_assert(is_less_than_comparable<K>::value, "Key type must be less-than comparable!");
};
struct x {};
int main() {
    map<x, int> intmap;
}

IDEONEは、私が取得したいと思っていた、すてきでクリーンなエラーメッセージでこのコードを喜んで拒否します(とにかく、nullptrを0に置き換えたら)。ただし、MSVCは静的アサーションを起動せず、このコードを正常にコンパイルします。メンバー関数をいくつか追加して呼び出しを開始した場合でも同様です。

4

2 に答える 2

1

is_less_than_comparable問題は、ではなく、メタ関数のVC++2010処理にありstatic_assertます。

コードを次のように変更した場合:

static const bool value = std::is_same<double, decltype(test<T>(true))>::value;

次に、どのオーバーロードが選択されたかに関係なく、falseになります。その後、アサーションが起動します。

明らかに間違ったオーバーロードが選択されており、SFINAEはcharリターンタイプの候補を削除していません。


より簡単なテスト(誤って印刷されます1):

#include <type_traits>
template<typename T> struct is_less_than_comparable {
    template<typename Test> static char test(decltype(*static_cast<Test*>(nullptr) < *static_cast<Test*>(nullptr)) b);
    template<typename Test> static int test(...);
    static const bool value = std::is_same<char, decltype(test<T>(true))>::value;
};
struct x {};
#include <iostream>
int main() {
    std::cout << is_less_than_comparable<x>::value << std::endl;
}

コンパイラーは、明白な理由もなく、演算子を提供しているbool operator<(x, x)ため、を生成しint is_less_than_comparable<T>::test<T>(bool)ます。ユーザー定義の比較演算子が指定されている場合、その戻りタイプは正しく取得されます。この演算子はヘッダーの1つを使用していません。ヘッダーを含めずに、decltype解決を再現できます。bool

これにより、適切なエラーが生成されます。

decltype(*(x*)nullptr < *(x*)nullptr) b;

error C2676: binary '<' : 'x' does not define this operator or a conversion to a type acceptable to the predefined operator

これは、VC++がテンプレートに依存する引数の2フェーズルックアップを実行しないことに関連していると思います。

于 2011-06-09T23:09:45.263 に答える
1

ここでの回答で何を探しているのかわからないので、VC++2010で正常に機能するタイプ特性を次に示します。

#include <type_traits>

namespace supports
{
    namespace details
    {
        struct return_t { };

        template<typename T>
        static T& make();
    }

    template<typename T>
    details::return_t operator <(T const&, T const&);

    template<typename T>
    struct less_than : std::integral_constant<
        bool,
        !std::is_same<
            decltype(details::make<T>() < details::make<T>()),
            details::return_t
        >::value
    > { };
}
于 2011-06-10T02:14:42.723 に答える