簡體   English   中英

檢查編譯時類中是否有靜態函數

[英]Check if static function is available in class at compile time

我目前正在連接一個具有多個實現的應用程序,用於單個目的。 在運行時檢查是否可以使用適當的實現,或者是否使用了回退。

為此,我希望所有實現都實現靜態函數static bool is_available()

由於靜態函數不能在底層基類中變為抽象,是否有一些預處理器魔法允許我輸出錯誤消息,如果該方法在子類中沒有靜態實現?

user9400869的答案相同,您可以使用SFINAE定義特征,以便在編譯時檢查類的可用性:

#include <type_traits>

template<class LIB, class = void>
struct is_available
: std::false_type
{};

template<class LIB>
struct is_available<LIB, std::enable_if_t<std::is_invocable_r<bool, decltype(LIB::is_available)>::value>>
: std::integral_constant<bool, LIB::is_available()>
{};

template<class LIB>
constexpr bool is_available_v = is_available<LIB>::value;

這意味着libs的C ++ 17和constexpr函數is_available

#include <iostream>

struct A {};
struct B { static constexpr bool is_available() { return false; } };
struct C { static constexpr bool is_available() { return true; } };

int main()
{
    std::cout << is_available_v<A> // 0
              << is_available_v<B> // 0
              << is_available_v<C> // 1 :)
              << '\n';
}

完整演示


如果C ++ 17不是一個選項,則std::is_invocable_r使用C ++ 14功能實現std::is_invocable_r

如果constexpr靜態成員函數不是庫類的選項,則不能依賴std::true_typestd::false_type並且必須使用運行時結果收集:

#include <type_traits>

template<class LIB, class = void>
struct is_available
{
    static bool value() { return false; }
};

template<class LIB>
struct is_available<LIB, std::enable_if_t<std::is_invocable_r<bool, decltype(LIB::is_available)>::value>>
{
    static bool value() { return LIB::is_available(); }
};

完整演示

你可以在編譯時使用模板測試它。 它是這樣的(抱歉沒有測試):

template<class Type_to_test, class Technical_Detail = void>
struct has_isAvilable : std::false_type {}

template<class Type_to_test>
struct has_isAvilable<Type_to_test, std::enable_if_t<
  std::is_same<bool,decltype(Type_to_test::is_available())>::value
> > : std::true_type {}

然后你可以在代碼中的某個地方使用:

static_assert(has_isAvilable<Implementation>::value,"Usefull error message");

實施是您希望測試的課程。 看看std::type_traits的例子。

我建議一個替代方案:標簽調度:

template <typename T> struct Tag {};

struct Base { /**/ };
struct Child1 : Base { /**/ };
struct Child2 : Base { /**/ };

bool is_available(Tag<Base>) {/*..*/}
bool is_available(Tag<Child1>) {/*..*/}
bool is_available(Tag<Child2>) {/*..*/}

Tag “阻止”繼承,與以下內容相反:

struct Base { static constexpr bool is_available() { return false; } };
struct Child1 : Base { static constexpr bool is_available() { return true; } };
struct Child2 : Base { /**/ };

static_assert(Base::is_available() == false);
static_assert(Child1::is_available() == true);
static_assert(Child2::is_available() == false); // Call Base::is_available()

暫無
暫無

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

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