模板参数困境

时间:2010-01-17 13:57:15

标签: c++ templates

我陷入两难境地。假设我有一个模板类:

template <typename ValueT>
class Array
{
public:
    typedef ValueT ValueType;
    ValueType& GetValue()
    {
        ...
    }
};

现在我想定义一个接收对类的引用并调用函数GetValue()的函数。我通常会考虑以下两种方式:

方法1:

template <typename ValueType>
void DoGetValue(Array<ValueType>& arr)
{
    ValueType value = arr.GetValue();
    ...
}

方法2:

template <typename ArrayType>
void DoGetValue(ArrayType& arr)
{
    typename ArrayType::ValueType value = arr.GetValue();
    ...
}

这两种方法几乎没有区别。即使调用这两个函数也看起来完全一样:

int main()
{
    Array<int> arr;
    DoGetValue(arr);
}

现在,哪两个是最好的?我可以想到一些缺点和优点:

方法1专业人士:

参数是一个真正的类而不是模板,因此用户更容易理解界面 - 参数必须是Array非常明确。在方法2中,您只能从名称中猜出它。我们在函数中使用ValueType,因此它比在Array中隐藏时更清晰,并且必须使用范围运算符进行访问。

此外,对于许多非模板精明的程序员来说,typename关键字可能会让人感到困惑。

方法2专业人士:

此功能更符合其目的。当我想到它的时候,我真的不需要这个类是Array。我真正需要的是一个具有方法GetValue和类型ValueType的类。就这样。也就是说,这种方法更通用。

此方法也较少依赖于Array类中的更改。如果更改了Array的模板参数怎么办?为什么它会影响DoGetValue?它并不关心如何定义Array。

Evey时间我有这种情况我不知道该选择什么。你有什么选择?

3 个答案:

答案 0 :(得分:4)

第二个更好。在你的第一个“专业人士”中,你说,“非常明确的是参数必须是数组”。但是说参数必须是一个数组是一个不必要的限制。在第二个示例中,任何具有合适GetValue函数的类都可以。由于这是一个不必要的限制,最好将其删除(第二个)而不是将其删除(第一个)。您将编写更灵活的模板,这在将来想要从不是数组的内容中获取值时非常有用。

答案 1 :(得分:1)

如果您的函数非常特定于ArrayType,并且没有其他模板可以满足其接口要求,请使用#1,因为它更短且更具体:随意读者被告知它在{{1 }}

如果其他模板可能与ArrayType兼容,请使用#2,因为它更通用。

但没有任何用处,因为它们很容易在它们之间进行转换。

答案 2 :(得分:0)

我的朋友提出了两种更极端的方法:

方法3:使您能够使用没有:: ValueType的类型。

template <typename ArrayType, typename ValueType = ArrayType::ValueType>
void DoGetValue(ArrayType& arr)
{
    ValueType value = arr.GetValue();
    ...
}

方法4:强制数组成为具有一个模板参数的类的一种很酷的方法。

template <template <typename> class ArrayType, typename ValueType>
void DoGetValue(ArrayType<ValueType>& arr)
{
    ValueType value = arr.GetValue();
    ...
}