簡體   English   中英

SFINAE用於用戶定義的轉換

[英]SFINAE for user-defined conversion

這個問題確實沒有背景。

使用SFINAE(直接或間接使用type_traits)檢查現有函數,成員函數等有很多種方法。 但:

第一個問題 :有沒有辦法檢查一個類是否實現了特定的用戶定義轉換運算符?

為了說明我的意思,請考慮此代碼。 我想在沒有任何斷言失敗的情況下運行此代碼:

#include <type_traits>
#include <cassert>

struct NotADouble {
};
struct Double {
    // explicit or not - you decide
    explicit operator double() {
        return 1.;
    }
};
// CORRECT THIS: ...
template<typename T,
    class = decltype(static_cast<double>(std::declval<T>()))>
int f(T) {
    return 1;
}
int f(...) {
    return 2;
}
// ... UNTIL HERE

int main() {
    assert(f(NotADouble()) == 2);
    assert(f(Double()) == 1);
    assert(f(3.) == 2);
    assert(f(3) == 2);
    assert(f(3.f) == 2);
}

f的當前實現檢查是否存在從Tdouble任何標准轉換序列,我假設在這種情況下這與std::is_convertible相同。

另一種方法是以下實現,它接受前兩個測試。

template<typename T>
int f(T, double (T::*)() = nullptr) {
    return 1;
}
int f(...) {
    return 2;
}

問題2 :即使NotADouble沒有實現任何轉換運算符,它似乎允許這個成員函數指針。 因此,究竟什么是double (T::*)() ,為什么它存在於任何類?

第一個問題:您可以創建輔助結構來檢查給定結構中是否存在已定義的轉換運算符(c ++ 14代碼):

#include <type_traits>
#include <iostream>

struct NotDouble { };
struct Double {
   explicit operator double() {
       return 1.0;
   }
};

template <class From, class To, class = void>
struct HasConversionOperator: std::false_type { };

template <class From, class To>
struct HasConversionOperator<From, To, decltype((&From::operator To), void())>: std::true_type { };

template <class From, class To, class = void>
struct HasExplicitConversion: std::false_type {};

template <class From, class To>
struct HasExplicitConversion<From, To, decltype(std::declval<To&>() = (To)std::declval<From&>(), void())>: std::true_type { };

template <class From, class To, class = void>
struct HasImplicitConversion: std::false_type {};

template <class From, class To>
struct HasImplicitConversion<From, To, decltype(std::declval<To&>() = std::declval<From&>(), void())>: std::true_type { };

template <class T>
std::enable_if_t<HasConversionOperator<T, double>::value && HasExplicitConversion<T, double>::value && !HasImplicitConversion<T, double>::value> is_double(T d) {
   std::cout << "has conversion to double" << std::endl;
}

template <class T>
std::enable_if_t<!HasConversionOperator<T, double>::value || !HasExplicitConversion<T, double>::value || HasImplicitConversion<T, double>::value> is_double(T) {
   std::cout << "don't have conversion to double" << std::endl;
}

int main() {
   is_double(Double{});
   is_double(NotDouble{});
}

輸出:

 has conversion to double don't have conversion to double 

第二個問題: double (T::*)()是一個帶有所有者T的任何成員函數指針的類型,它返回一個不帶任何參數的double。 請記住,不僅轉換運營商有這樣的簽名。 更甚至,如果類T沒有任何返回double的成員函數並且沒有參數,則完全允許創建這樣的指針類型,一個只是無法用任何值填充指針類型的變量。 。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM