Variadic 模板回调接口 class 实例化不能重载

Variadic template callback interface class instanciation cannot be overloaded

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

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

#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.
}

通过添加新的 child class,

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() {};
     ^~~~~~~~~

而不是专门化模板

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

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

class NoneT {};

class ListModel : public MotherA
{
};
class FinalLChild : public Interface<ListModel,NoneT>, 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 ); 
    };

};

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

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

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

我向SFINAEenable/disable建议第二个如下

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

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

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

Interface() : Base() {};

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