C++ 部分模板专业化 - 设计简化

Posted

技术标签:

【中文标题】C++ 部分模板专业化 - 设计简化【英文标题】:C++ Partial template specialization - design simplification 【发布时间】:2015-04-24 09:15:10 【问题描述】:

我正在研究管道/数据流设计模式。我有一个类“算法数据输出”(AlgorithmOutput),它充当两个连接的网段之间的接口。特别是,它提供了方法模板getOutput<size_t N>,用于从“数据发送器”类型的对象输出数据。

当前的设计基于用户从类AlgorithmOutput 派生并提供有限数量的方法模板getOutput<size_t N> 的实现的想法。我还需要能够允许用户通过方法getOutput 提供他们自己的自定义返回类型(即返回类型不能是多态的)。此外,必须让getOutput 的所有实现都能够访问定义为方法所属类的成员的同一数据集。

当前的解决方案在用户派生的类中使用部分显式特化来定义方法getOutput 的不同实现。我想简化解决方案,并希望在不丢失当前设计功能的情况下实现这一点的任何想法。

编辑:我只关心从用户的角度实现方法getOutput 的难易程度。我不关心基类的实现有多复杂。

派生类的实现示例:

class PipeOutputClass: public AlgorithmOutput<PipeOutputClass>


public:

    template <size_t N>
    auto getOutput(size_t c_Idx) const
        
            return getOutputImpl<N>::apply(this, c_Idx);
        

    template<size_t N, typename S> friend struct getOutputImpl;

    template<size_t N, typename = void>
    struct getOutputImpl
    
        static auto apply(
            PipeOutputClass const* p_Self,
            size_t c_Idx
            )
            
                throw std::runtime_error("Wrong template argument.");
            
    ;

    template <typename S>
    struct getOutputImpl<0, S>
    
        static std::unique_ptr<double> apply(
            PipeOutputClass const* p_Self,
            size_t c_Idx
            )
            
                std::unique_ptr<double> mydouble(new double(10));
                return mydouble;
            
    ;

    template <typename S>
    struct getOutputImpl<1, S>
    
        static std::unique_ptr<int> apply(
            PipeOutputClass const* p_Self,
            size_t c_Idx
            )
            
                std::unique_ptr<int> myint(new int(3));
                return myint;
            
    ;

;

【问题讨论】:

S 模板参数是干什么用的? 需要的N是如何定义的? @Jarod42 如果我正确理解了您的问题,则所需的N 由用户(即课程的开发人员)在getOutputImpl 中定义。但是,有一个更好的解决方案 - 请参阅接受的答案。它也可以更好地解释我想要做什么。 我的意思是,我们怎么知道PipeOutputClass 应该实现01(而不是2)? @Jarod42 我想我现在更好地理解了你的问题。 PipeOutputClass 可以拥有用户喜欢的任意数量的输出端口,前提是它们是按顺序定义的。通过将指向它们的指针存储在向量容器中,这些输出函数在基类(即AlgorithmOutput)中进行管理。您可以在此处找到更多详细信息:link 【参考方案1】:

您可以使用标签调度来避免部分专业化的需要。简化版:

//we'll use this to overload functions based on a size_t template param
template <size_t N>
struct Size2Type;

class PipeOutputClass

public:
    template <size_t N>
    auto getOutput(size_t c_Idx) const
    
        //use Size2Type to tag dispatch
        return getOutputImpl(Size2Type<N>, c_Idx);
    

    //default version for when we don't explicitly provide an overload
    template <size_t N>
    auto getOutputImpl(Size2Type<N>, size_t c_Idx) const
    
         throw std::runtime_error("Wrong template argument.");
    

    //overload for when N = 0
    std::unique_ptr<double> getOutputImpl (Size2Type<0>, size_t c_Idx) const
    
        std::unique_ptr<double> mydouble(new double(10));
        return mydouble;
    

    //overload for when N = 1
    std::unique_ptr<int> getOutputImpl (Size2Type<1>, size_t c_Idx) const
    
        std::unique_ptr<int> myint(new int(3));
        return myint;
    
;

【讨论】:

以上是关于C++ 部分模板专业化 - 设计简化的主要内容,如果未能解决你的问题,请参考以下文章

使用 STL 容器的部分 C++ 模板特化

这是为成员函数的 C++ 模板部分特化构造类的好方法吗?

指针的 C++ 模板特化?

部分类模板专业化是这个设计问题的答案吗?

如何避免“模板参数在部分专业化中无法推导”

为啥接受数组的 C++ 模板并不比接受 GCC 5.3 和 Clang 4.0 的指针更专业?