c++ - 使用可变修改类型实例化模板

标签 c++ templates c++11

我类的一个成员方法以枚举类型作为参数:它对不同的枚举产生不同的副作用。我想知道是否可以将模板用作查找表,我想到了两种可能的解决方案,但似乎都不起作用:

//// 1 ////

class A {

    public:

    enum AEnum : uint8_t { first, second, ... };

    private:

    template<AEnum N, typename T>
    struct impl {
        static void do_sth(T t) { ... };
    };

    template<typename T>
    struct impl<first, T> {
        static void do_sth(T t) { ... };
    };

    public:


    template<typename T>
    void do_sth(AEnum e, T t) {
        impl<e, T>::do_sth(t);
    }

}

//// 2 ////

class A {

    public:

    enum AEnum : uint8_t { first, second, ... };

    private:

    template<typename T_enum, typename T>
    struct impl {
        static void do_sth(T t) { ... };
    };

    template<typename T>
    struct impl<uint8_t[2], T> { // A::first
        static void do_sth(T t) { ... };
    };

    public:


    template<typename T>
    void do_sth(AEnum e, T t) {
        impl<uint8_t[static_cast<uint8_t>(e) + 1u], T>::do_sth(t);
    }

}

以这种方式编码真的是个坏主意吗?

@奥利查尔斯沃思

What's wrong with a switch statement?

do_sth 的第二个参数 (T) 支持的类型随 e 的值而变化,例如A::first 支持积分,A::second STL 容器,例如:

    template<typename T>
    void do_sth(AEnum e, T t) {
        switch(e) {
            case first:
                std::cout << &t << std::endl;
                break;
            case second:
                std::cout << t.data() << std::endl;
                break;
            default:
                break;
    }

A a;
a.do_sth(A::first, 0);

最佳答案

您必须使 AEnum arg 成为 do_sth 的模板参数:


 template<AEnum e, typename T>
    void do_sth(T t) { ... }

...并将其命名为 a.do_sth<A::first>(0) .

或者,您可以编写单独的函数(do_sth_integraldo_sth_container、...),或者,如果对于特定 T 只有一个正确的操作过程,则推导出给定的“正确”枚举值T 使用元编程/重载技巧。

例如,这是一种编写两个函数的方法,例如检测数字类型和容器类型:


//The extra dummy argument is invalid for types without a nested 
//"iterator" typedef
template<typename T>
void do_sth(T t, typename T::iterator * = 0)
{
    //container type code
}

//The dummy arg is invalid for types without a 
//std::numeric_limits specialization
template<typename T>
void do_sth(T t, 
typename boost::enable_if_c<std::numeric_limits<T>::is_specialized>::type * = 0) 
{
    //numeric type code
}

当然,如果您传递的 T 具有迭代器 typedef 和 numeric_limits 特化,或者两者都没有,这将失败。

如果对于特定的 T 只有一个合理的操作,并且很难正确猜测应该对未知的 T 使用哪个重载,那么您可以使用用户必须明确专门化的特征类,或者只要求用户专门化“impl”或调度类。

你不能写一个函数来做类似 3.data() 的事情,即使程序运行时从未调用该代码路径。编译器不知道它永远不会被调用,并且在任何情况下,它都会以导致诊断错误所需的方式违反语言的类型系统。

关于c++ - 使用可变修改类型实例化模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3639476/

相关文章:

C++ 多类型模板使用指南

c++ - 如何传递模板模板非类型成员函数指针?

C++11 在 Lambda 中捕获成员变量

c++ - 给 long long c++ 赋值时应该使用 LL

c++ - 如何在C++中拆分程序

c++ - 非限定或指针/引用类型的特征

c++ - Qt 终止由 QConcurrent::run 生成的线程

c++ - 通过 WinSocket 客户端/服务器应用程序重用套接字

c++ - 如何避免序列化器和容器序列化器之间的循环模板依赖?

c++11 什么是第一个?构造函数还是默认值?