简体   繁体   English

检查编译时类中是否有静态函数

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

I am currently wiring an application that has several implementations for a single purpose. 我目前正在连接一个具有多个实现的应用程序,用于单个目的。 It is checked at runtime if the appropriate implementation can be used or if a fallback is used. 在运行时检查是否可以使用适当的实现,或者是否使用了回退。

For that purpose I want all implementations to implement a static function static bool is_available() . 为此,我希望所有实现都实现静态函数static bool is_available()

As static functions cannot be made abstract in the underlying base class, is there some preprocessor magic that will allow me to output an error message if the method is not statically implemented in the child class? 由于静态函数不能在底层基类中变为抽象,是否有一些预处理器魔法允许我输出错误消息,如果该方法在子类中没有静态实现?

In the same vein that user9400869's answer , you can define a trait using SFINAE to check, at compilation time, the availability of your classes: 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;

This implies C++17 and constexpr functions is_available for the libs: 这意味着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';
}

Full demo 完整演示


If C++17 is not an option, you can implement std::is_invocable_r using C++14 features only. 如果C ++ 17不是一个选项,则std::is_invocable_r使用C ++ 14功能实现std::is_invocable_r

If constexpr static member functions are not an option for your library classes, you cannot rely on std::true_type and std::false_type and must use run-time result gathering: 如果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(); }
};

Full demo 完整演示

you could test this at compiletime with templates. 你可以在编译时使用模板测试它。 It goes something like this (sorry not tested): 它是这样的(抱歉没有测试):

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 {}

Then you can use somewhere in your code: 然后你可以在代码中的某个地方使用:

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

Where Implementation is the class you wish to test. 实施是您希望测试的课程。 Have a look at std::type_traits for examples of this. 看看std::type_traits的例子。

I would suggest an alternative: tag dispatching: 我建议一个替代方案:标签调度:

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 "blocks" Inheritance, contrary to: 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