我在下面的示例中有三个getColors函数。
问题:如何将threee getcolors函数转换为一个泛型函数?
struct EcvColorMap{
vector<Scalar> getColors(){
vector<Scalar> result;
//....
return result;
}
};
struct Scalar{
int val[3];
};
vector<Scalar> getColors(vector<Scalar> colors){
return colors;
}
vector<Scalar> getColors(Scalar color){
return{ color };
}
vector<Scalar> getColors(EcvColorMap color_map){
return color_map.getColors();
}
答案 0 :(得分:4)
问题是:功能的主体是不同的,如果你试图制作一个通用的,其他部分专业化,完全专业化,如
template<typename T> vector<Scalar> getColors(T colors) {
return {colors};
}
//template<typename T> vector<Scalar> getColors(vector<T> colors) { // Not really necessary - see list initialization
// return colors;
//}
template<> vector<Scalar> getColors<EcvColorMap>(EcvColorMap colors) {
return colors.getColors();
}
你仍然需要为三个不同的模板编写代码而根本没有任何收益(编译时优势还是代码重用?)。
我个人的建议:不要使用模板,因为它很酷,在实际需要时使用它们。在大型软件视图中,这是至关重要的。你发布的设计对我有意义。
答案 1 :(得分:2)
您无需转换这些功能,这一点非常明确。
您的三个功能具有不同的主体,因此您无法将它们放在单个模板功能中。您可以使用模板函数替换它们,并使用这些类型的特化,但它只会使它复杂化。
答案 2 :(得分:1)
正如Marco的回答所指出的,在这种情况下,你必须权衡使用模板的优缺点。
话虽如此,你可以检查一种典型的方法,使用特征;这通常是在您希望抽象出可能以不同方式发生的事情时完成的。所以你可以这样发送实际的 getter :
template<typename T>
vector<Scalar> getColors(T colors)
{
return getter<T>::get(colors);
}
然后,您将为每个实体构建一些特征
template<typename T>
struct getter; // types not specified in your traits system will not work
template<>
struct getter<vector<Scalar>> {
static vector<Scalar> get(vector<Scalar> colors) {
return colors;
}
};
template<>
struct getter<Scalar> {
static vector<Scalar> get(Scalar color) {
return { color };
}
};
template<>
struct getter<EcvColorMap> {
static vector<Scalar> get(EcvColorMap color) {
return color_map.getColors();
}
};
没有魔力,你仍然需要手动编写所有代码。 唯一的例子就是,如果你必须在更多的地方使用 getter ,那么你就可以随时写下:
template<typename T>
void FunctionN(T arg)
{
auto val = getter<T>::get(arg);
// do stuff like printing etc
}
因此,越大的N越能从抽象出get
操作中获得越多。类似地,set
操作可以被分割等等。
答案 3 :(得分:0)
前两个函数使用Scalar
和vector<Scalar>
类型,这两个函数都可用于构造函数vector<Scalar>
。您可以将这些功能缩减为支持任何可转换为Scalar
或vector<Scalar>
的类型的函数。
template <class T>
std::vector<Scalar> getColors(const T& data)
{
return { data };
}
// Overloads do not need to be a template.
std::vector<Scalar> getColors(const EcvColorMap& data)
{
return { data.getColors() };
}
要消除最终getColors
函数(如果有意义),您可以在EcvColorMap
中提供显式转换运算符。这样就可以将EcvColorMap
的实例传递给上面显示的getColors
版本。
struct EcvColorMap
{
explicit operator std::vector<Scalar>() const
{
std::vector<Scalar> result;
//....
return result;
}
};
通过以上两项更改,您现在可以针对问题中列出的所有类型调用getColors
。
std::vector<Scalar> colors;
Scalar color;
EcvColorMap colormap;
getColors(color);
getColors(colors);
getColors(colormap);
如果提供转换运算符是有意义的,则可以通过构造和赋值来消除getColors
函数。
std::vector<Scalar> colors;
Scalar color;
// Construct
std::vector<Scalar> new_colors1{color};
std::vector<Scalar> new_colors2{colors};
// Assign.
std::vector<Scalar> new_colors;
new_colors = colors;
new_colors = { color };
new_colors = colormap.getColors();