gpt4 book ai didi

c++ - Variadic模板回调接口(interface)类实例化不能重载

转载 作者:行者123 更新时间:2023-11-30 04:45:50 24 4
gpt4 key购买 nike

我想做的是拥有一个仅包含函数成员的回调接口(interface)。今天,我有 2 个最终类,它们使用此接口(interface)通过在 CallbackStore 中保存特定回调来定义它们的行为。

根据我的约束(here),我实现的是以下最小编译代码,但只有一个子类:

#include <iostream>
#include <stdint.h>

using namespace std;

static constexpr int STORE_SIZE = 4;

void* operator new(size_t size)
{
cout << "ERROR HEAP USED" << endl;
}

template<typename T, size_t storeSize>
class CallbackStore
{
public:

CallbackStore() : that_(nullptr) {};
CallbackStore(T* that) : that_(that) {};

using CallbackCondition = bool (*) (T*);
using CallbackAction = void (*) (T*,int);
struct Step
{
CallbackCondition pCallbackCondition;
CallbackAction pCallbackAction;
};
void setStep(int stepId,CallbackCondition pCallbackCondition, CallbackAction pCallbackAction)
{
if(stepId<storeSize)
{
store[stepId].pCallbackCondition = pCallbackCondition;
store[stepId].pCallbackAction = pCallbackAction;
}
else
{
cout << "pointer error" << endl;
}
}
void callStep(int stepId, int param)
{
if((stepId<storeSize) &&
(store[stepId].pCallbackCondition != nullptr) &&
(store[stepId].pCallbackAction != nullptr) &&
(that_ != nullptr))
{
bool isActive = (*(store[stepId].pCallbackCondition))(that_);
if(isActive) {(*(store[stepId].pCallbackAction))(that_,param);}
}
else
{
cout << "pointer error" << endl;
}

}
Step store[storeSize];
T* that_;
};

template<typename Base, typename... ArgT>
class Interface : public Base // interface
{
public:
Interface() : Base() {};
Interface(ArgT... arg) : Base(arg...) {};

public:
static bool True(Base* baseInstance)
{
return true;
}
static bool IsNegative(Base* baseInstance)
{
return ((static_cast<Base*>(baseInstance))->getValue() < 0);
}
static bool IsNull(Base* baseInstance)
{
return ((static_cast<Base*>(baseInstance))->getValue() == 0);
}
static bool IsPositive(Base* baseInstance)
{
return (IsNegative(baseInstance) == false);
}
static void PrintValue(Base* baseInstance, int value)
{
cout << "print this value : " << value << "." << endl;
}
};


template<typename Base>
class Interface<Base,void>// interface
{
public:
Interface() : Interface<Base,void>() {};
};

class MotherA
{
public:
MotherA(){};
MotherA(int x): x_(x){};
int getValue() { return x_; }
void setValue(int x) { x_ = x; }

protected:
int x_ = -3;
};

class ListModel : public MotherA
{
};
class FinalLChild : public Interface<ListModel>, public CallbackStore<ListModel, STORE_SIZE>
{
public:
FinalLChild(): Interface(), CallbackStore(this)
{
setStep(0, &Interface::IsNegative, &Interface::PrintValue );
setStep(1, &Interface::IsNegative, &Interface::PrintValue );
setStep(2, &Interface::IsNull, &Interface::PrintValue );
setStep(3, &Interface::True, &Interface::PrintValue );
};

};

class ValueModel : public MotherA
{
public:
ValueModel() : MotherA(), y_(0) {};
ValueModel(int x,int y) : MotherA(x), y_(y) {};
void reset(){x_= y_;};
int y_ = 0;
};

class ValueChild : public Interface<ValueModel,int,int>, public CallbackStore<ValueModel, STORE_SIZE>
{
public:
ValueChild() : Interface(), CallbackStore(nullptr){};
ValueChild(int x,int y): Interface(x,y), CallbackStore(this){};
};

class FinalVChild : public ValueChild
{
public:
FinalVChild():ValueChild(2,0)
{
setStep(0, &Interface::IsPositive, &Interface::PrintValue );
setStep(1, &Interface::IsPositive, &Interface::PrintValue );
setStep(2, &Interface::IsNull, &Interface::PrintValue );
setStep(3, &Interface::IsNull, &Interface::PrintValue );
};
};


int main()
{
FinalVChild c;
for(int i = 0; i < STORE_SIZE; i++)
{
c.callStep(i,8);
}
cout << "reset:\n";
c.reset();
for(int i = 0; i < STORE_SIZE; i++)
{
c.callStep(i,8);
}
// shall print "print this value : 8." 3 times if x_ is null, twice if x_ is negative.
}

通过添加一个新的子类,

class ListModel : public MotherA
{
};

class FinalLChild : public Interface<ListModel>, public CallbackStore<ListModel, STORE_SIZE>
{
public:
FinalLChild(): Interface(), CallbackStore(this)
{
setStep(0, &Interface::IsNegative, &Interface::PrintValue );
setStep(1, &Interface::IsNegative, &Interface::PrintValue );
setStep(2, &Interface::IsNull, &Interface::PrintValue );
setStep(3, &Interface::True, &Interface::PrintValue );
};

};

在 main() 中

    FinalLChild d;
cout << "d:\n";
for(int i = 0; i < STORE_SIZE; i++)
{
d.callStep(i,8);
}

这会引发以下编译错误:

main.cpp: In instantiation of ‘class Interface<ListModel>’:
<span class="error_line" onclick="ide.gotoLine('main.cpp',113)">main.cpp:113:57</span>: required from here
main.cpp:65:5: error: ‘Interface::Interface(ArgT ...) [with Base = ListModel; ArgT = {}]’ cannot be overloaded
Interface(ArgT... arg) : Base(arg...) {};
^~~~~~~~~
main.cpp:64:5: error: with ‘Interface::Interface() [with Base = ListModel; ArgT = {}]’
Interface() : Base() {};
^~~~~~~~~

最佳答案

我想问题出在这对构造函数上

Interface() : Base() {};
Interface(ArgT... arg) : Base(arg...) {};

ArgT... 为空列表时,它们是相同的构造函数并发生冲突。

我建议 SFINAE 如下启用/禁用第二个

template <bool B = (sizeof...(ArgT)>0u), std::enable_if_t<B, bool> = true>
Interface(ArgT... arg) : Base(arg...) {};

这样,第二个构造仅在 ArgsT... 不为空时启用。

另一种方法是避免 SFINAE(启用的第二个构造函数),但将其转换为模板,使用未使用的模板参数的可变未命名列表,因此第一个具有优先权

Interface() : Base() {};

template <typename ...>
Interface(ArgT... arg) : Base(arg...) {};

关于c++ - Variadic模板回调接口(interface)类实例化不能重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57054421/

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