gpt4 book ai didi

c++ - 检查成员是否存在并调用它或什么也不做

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:02:59 25 4
gpt4 key购买 nike

我有一个带有 init() 方法的模板类,如果它存在,则必须调用子类方法。基类的方法 init() 永远调用。

template <class T>
class Base
{

template<typename... Args>
void init(Args... args);

T subj;

explicit Base() { subj = new T(); }
}


template<typename... Args>
Base<T>::init(Args... args)
{
invoke_if_exists<&T::init,subj>(args); // <-- that moment
}

需要实现 invoke_if_exists 模板。算法应该是这样的代码

if ( method_exists(T::init) )
{
subj->init(Args...);
}

我需要将它包装到模板中

非常感谢。

[更新]:

让我尝试稍微广泛地解释一下。

class Foo
{
// ... and there is no init()
};

class Right
{
void init() { ... }
/// ...
}


auto a = new Base<Foo>();
auto b = new Base<Right>();

a->init(); // there is no call for Foo::init();
b->init(); // there is correct call for Right::init();

我想使用 invoke_if_exists<>不仅是 init() 方法,它可以是任何方法。

最佳答案

一个数据和类型接收器,它接受类型和数据,但不对它们做任何事情:

struct sink {
template<typename... Us>
void operator()(Us&&... us) const {}
};
template<typename... Ts>
struct type_sink:std::true_type {};

然后我们创建一个模板 invoke_init_if_exists,它接受一个目标类型T和一组参数,如果T* ->init 可以用这些参数调用,这样做。否则,它会将这些东西扔到上面的数据接收器中:

template<typename T,typename ArgTypes,typename=void>
struct invoke_init_if_exists:sink {};
template<typename T,template<typename...>class Pack,typename... Args>
struct invoke_init_if_exists<T,
Pack<Args...>,
typename std::enable_if< type_sink<
decltype( std::declval<T*>()->init( std::declval<Args>()... ) )
>::value >::type
>
{
void operator()( T* target, Args&&... args ) const {
target->init( std::forward<Args>(args)... );
}
};

然后我们使用它来实现您的 init 方法:

template<typename... Args>
Base<T>::init(Args&&... args)
{
invoke_init_if_exists<T, type_sink<Args...>>()(&subj, std::forward<Args>(args)...);
}

我们在这里创建我们的助手类,它可以是一个 sink 或者转发给 init 的东西,这取决于对 init 的调用是有效。

我们最终不得不做这样的事情,因为除非 T 已经有一个方法 init。因此,我们必须编写一个自定义类,在 SFINAE 上下文中执行 T::init 查找,如果失败则回退到什么都不做。

关于c++ - 检查成员是否存在并调用它或什么也不做,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19959734/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com