5

を使用した非常に単純な関数がありますstatic_assertstatic_assert問題は、関数宣言に関連する動作、特に戻り値の型を推測したいことです。コンパイラが戻り値の型の推定に失敗するstatic_assertに起動できるように、を挿入する場所がないようです。

ここまでは戻り値の型推定と静的アサーションを構造体に入れました。これにより、アサーションが起動されます。これは素晴らしいことですが、型推論でエラーが発生します。これは、私が除去したいノイズです。

#include <type_traits>
#include <functional>
#include <memory>
#include <map>
#include <iostream>
#include <string>
#include <cstdio>
#include <tuple>
#include <sstream>
#include <vector>
#include <algorithm>

template<typename T, typename X> struct is_addable {
    template<typename Test, typename Test2> static char test(decltype(*static_cast<Test*>(nullptr) + *static_cast<Test2*>(nullptr))*);
    template<typename Test, typename Test2> static int test(...);
    static const bool value = std::is_same<char, decltype(test<T, X>(nullptr))>::value;
};
template<typename T, typename X> struct is_addable_fail {
    static const bool value = is_addable<T, X>::value;
    static_assert(value, "Must be addable!");
    typedef decltype(*static_cast<T*>(nullptr) + *static_cast<X*>(nullptr)) lvalue_type;
};

template<typename T1, typename T2> auto Add(T1&& t1, T2&& t2) -> typename is_addable_fail<T1, T2>::lvalue_type {
    return std::forward<T1>(t1) + std::forward<T2>(t2);
}

struct f {};

int main() {
    std::cout << Add(std::string("Hello"), std::string(" world!"));
    Add(f(), f());
}
4

2 に答える 2

0

質問を誤解しているかもしれませんが、次のような SFINAE は目的を満たしていますか?

template<typename T = int> void Add(...) {
    static_assert(sizeof(T) == 0, "Must be addable!");
}

template<typename T1, typename T2> auto Add(T1&& t1, T2&& t2) ->
  decltype(std::forward<T1>(t1) + std::forward<T2>(t2)) {
    return std::forward<T1>(t1) + std::forward<T2>(t2);
}

これはideoneのテストです。欠点は、それAddを繰り返さなければならないことです。

編集: これが厳密に標準に準拠しているかどうかは完全にはわかりませんが、次の回避策は役立ちますか? (イデオンのテスト)

template<typename T1, typename T2> void Add(T1 volatile&&, T2 volatile&&) {
    static_assert(sizeof(T1) == 0, "Must be addable!");
}
于 2011-06-27T22:13:33.763 に答える
0

候補セットの作成方法と SFINAE のため、これは不可能です。関数のシグネチャが完全に決定される前にアサートできる場合は、関数が使用されるものであると決定される前にアサートする必要があります。

手順の順序は基本的に次のとおりです。

  • 一致する関数を見つける
  • 推定されたパラメーターを関数の引数と戻り値の型に置き換えます。
  • 失敗したものを捨てる (SFINAE)
  • 残っている場合は、それを使用してください。

いつアサートを起動しますか?

パラメータ置換中に起動すると、SFINAE が除外されます。その後いつでも起動すると、戻り値の型は既に決定されています (遅すぎます)。

于 2011-06-27T18:25:02.623 に答える