C++ C++;部分模板专门化-设计简化
我正在研究管道/数据流设计模式。我有一个类“AlgorithmData output”(C++ C++;部分模板专门化-设计简化,c++,templates,c++11,pipeline,partial-specialization,C++,Templates,C++11,Pipeline,Partial Specialization,我正在研究管道/数据流设计模式。我有一个类“AlgorithmData output”(AlgorithmOutput),它充当两个连接的网段之间的接口。特别是,它提供了方法模板getOutput,用于从“数据发送器”类型的对象输出数据 当前的设计基于这样一种理念,即用户从类AlgorithmOutput派生,并提供有限数量的方法模板getOutput的实现。我还需要允许用户通过方法getOutput提供自己的自定义返回类型(即返回类型不能是多态的)。此外,有必要让getOutput的所有实现能
AlgorithmOutput
),它充当两个连接的网段之间的接口。特别是,它提供了方法模板getOutput
,用于从“数据发送器”类型的对象输出数据
当前的设计基于这样一种理念,即用户从类AlgorithmOutput
派生,并提供有限数量的方法模板getOutput
的实现。我还需要允许用户通过方法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;
}
};
};
class PipeOutputClass:公共算法输出
{
公众:
模板
自动获取输出(大小c_Idx)常量
{
返回getOutputImpl::apply(this,c_Idx);
}
模板友元结构getOutputImpl;
模板
结构getOutputImpl
{
静态自动应用(
PipeOutputClass常量*p_Self,
尺寸
)
{
抛出std::runtime_错误(“错误的模板参数”);
}
};
模板
结构getOutputImpl
{
静态标准::唯一\u ptr应用(
PipeOutputClass常量*p_Self,
尺寸
)
{
标准::唯一的我的双(新双(10));
返回mydouble;
}
};
模板
结构getOutputImpl
{
静态标准::唯一\u ptr应用(
PipeOutputClass常量*p_Self,
尺寸
)
{
std::unique_ptr myint(新int(3));
返回myint;
}
};
};
您可以使用标记分派来避免部分专门化的需要。简化版:
//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;
}
};
//我们将使用它根据size\t模板参数重载函数
模板
结构大小2类型{};
类PipeOutputClass
{
公众:
模板
自动获取输出(大小c_Idx)常量
{
//使用Size2Type标记分派
返回getOutputImpl(Size2Type{},c_Idx);
}
//未显式提供重载时的默认版本
模板
自动getOutputImpl(Size2Type,size\t c\u Idx)常量
{
抛出std::runtime_错误(“错误的模板参数”);
}
//N=0时的过载
std::unique_ptr getoutputinpl(Size2Type,size_t c_Idx)常量
{
标准::唯一的我的双(新双(10));
返回mydouble;
}
//N=1时的过载
std::unique_ptr getoutputinpl(Size2Type,size_t c_Idx)常量
{
std::unique_ptr myint(新int(3));
返回myint;
}
};
s模板参数是什么?所需的N
是如何定义的?@Jarod42如果我正确理解了您的问题,所需的N
由用户(即类的开发人员)在getOutputImpl
中定义。然而,有一个更好的解决方案——见公认的答案。它也可以更好地解释我试图做的事情。我的意思是,我们如何知道PipeOutputClass
应该实现0
和1
(而不是2
)?@Jarod42我想我现在更理解你的问题了PipeOutputClass
可以拥有用户喜欢的任意多个输出端口,前提是它们是按顺序定义的。这些输出函数通过将指向它们的指针存储在向量容器中,在基类(即,AlgorithmOutput
)中进行管理。您可以在此处找到更多详细信息: