c++ - 在编译时将枚举与模板类相关联

标签 c++ templates types type-conversion

我有一个模板类如下:

template<typename A> struct TaskInfo{
    typedef A       _A;
    static void bar(A a){blah blah...} };

template <typename TaskInfo> class Task   {
    typedef typename TaskInfo::_A A;
    bar(A a){
        blah blah...
        TaskInfo::bar(a);
    }   
}

我有一个包含这些类集合的对象:

using TaskInfoX= TaskInfo<int>; //ignore the bar implementation for the time being.
using TaskInfoY= TaskInfo<double>;

class TaskCollection(){ 
    TaskCollection(){
        auto Task1=new Task<TaskInfoX>;
        auto Task2=new Task<TaskInfoY>;
        Register(Task1);
        Register(Task2);
    }
Register(...);
}

我想知道是否可以定义枚举列表:

enum TaskEnum
{
    Etask1,
    Etask2
};

和函数 getTask 这样在我的应用程序中我可以拥有:

int main {
    TaskCollection collection;
    int testInt;
    double testDouble;
    collection.getTask(Etask1)->bar(testInt);
    //collection.getTask(Etask1)->bar(testDouble);  //want compile error.
    collection.getTask(Etask2)->bar(testDouble);
}

我知道我可以拥有 CRTP 或虚拟继承等价物,允许我为 bar() 传递可变参数,但我想在编译时对 bar 函数的参数进行类型检查。这在 C++ 中是不可能的吗?

更新:为打字错误道歉。这本来是:getTask(task1)。基本上,外界并不知道任务的底层结构,只能根据它们的公共(public)枚举 key 了解它们。另请注意,通常会有额外的任务可能会重用 typeInfoX 参数。

最佳答案

首先,要在类型不完全匹配时出现错误,您可以使用以下命令:

template <typename T>
class Task
{
public:
    using type = typename T::type;

    void bar(type a) { T::bar(a); }

    template <typename U>
    std::enable_if_t<!std::is_same<std::decay_t<U>, type>::value>
    bar(U&&) = delete;
};

然后,在一些助手的帮助下:

template <TaskEnum> struct TaskMap;

template <> struct TaskMap<Etask1> { using type = Task<TaskInfoX>; };
template <> struct TaskMap<Etask2> { using type = Task<TaskInfoY>; };

您的收藏可能是这样的:

class TaskCollection
{ 
public:
    Task<TaskInfoX> taskX;
    Task<TaskInfoY> taskY;

    template <TaskEnum E>
    typename TaskMap<E>::type&
    getTask();
};

template <>
Task<TaskInfoX>& TaskCollection::getTask<Etask1>() { return taskX; }

template <>
Task<TaskInfoY>& TaskCollection::getTask<Etask2>() { return taskY; }

最终用法:

collection.getTask<Etask1>().bar(testInt);
collection.getTask<Etask1>().bar(testDouble);//error:call to deleted member function 'bar'
collection.getTask<Etask2>().bar(testDouble);

Demo

关于c++ - 在编译时将枚举与模板类相关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40407375/

相关文章:

c++ - 设置QScrollBar的 slider 大小与内容对应

c++ - 将 std::array 作为模板可变参数函数的参数传递

typescript - Mikro-orm 属性类型日期和字段类型字符串的迁移错误

c++ - 范围枚举 : error: cannot convert ‘int’ to ‘Handle’ in initialization

c++ - 消除 HTML 的最佳 C/C++ 库?

c++ - 几个 Makefile 问题

c++ - C++严格混叠规则使用Qt和QLinkedList编译错误

c++ - 用于检查成员是否存在的模板特化

c++ - 将 std::__cxx11::string 转换为 std::string

visual-c++ - Visual C++ 中 UCHAR 和 WCHAR 有什么区别?