C++:如何在类和基元上使用模板

C++: how to use a template on both classes and primitives?

本文关键字:C++      更新时间:2023-10-16

我有一个关于可以与类或基元类型的参数一起使用的模板的问题。以下是一些示例代码:

(注意:我有更复杂的真实代码,下面的代码没有用,但它再现了相同的问题)

template<typename T>
class Foo
{
  T value;
public:
  Foo() {}
  const T& getValue() const { return value; }
  Foo& setValue(const T& other) { 
    value = other; return *this; 
  }
};
struct Bar
{
  int x;
  Bar() : x(3) {}
};
int doit()
{
  Foo<int> fooint;
  Bar bar;
  bar.x = 44;
  Foo<Bar> foobar;
  fooint.setValue(3);      // warning here
  foobar.setValue(bar);
  int y = foobar.getValue().x + fooint.getValue();
  return y;
}

我得到了关于fooint.setValue():的编译器注释

value copied to temporary, reference to temporary used

我理解这句话。我想知道的是,如果我要将Foo与基元和类/结构类型一起用作模板参数,我应该如何处理Foo::setValue()

我认为setValue(const T& other)是通过引用传递常量类的正确方法签名。

有没有一种方法可以使setValue()对Foo<int>Foo<Bar>都"做正确的事情"?

像在setValue()中那样将临时值绑定到常量引用是完全合法的。发布此备注的英特尔C++在这种情况下没有任何帮助。

编辑:我猜TI编译器是基于英特尔的,对我来说,英特尔会在这一行发布以下诊断:

test.cc(28): remark #383: value copied to temporary, reference to temporary used
    fooint.setValue(3);      // warning here

诊断在上进行了讨论http://software.intel.com/en-us/articles/cdiag383/上面写着

对于矢量的推回功能,可以安全地忽略此警告。向量将自变量复制到自己的存储器中;它从不存储原始论点。因此,使用临时工是完全安全的。

在您的情况下,您也在复制参数,因此它也可以被忽略。

我认为您的代码没有任何问题。GCC编译它时没有错误或警告。

要回答让Foo<T>::setValue()做"正确的事情"的最后一个问题,可以考虑使用模板专业化来实现这一点——这是模板元编程中使用的一种相当常见的技术。例如:

template <typename T>
struct Ref_or_Value
{
    typedef T& type;
};
template <typename T>
struct Ref_or_Value<T *>
{
    typedef T* type;
};
template <>
struct Ref_or_Value<int>
{
    typedef int type;
};
// add other primitive types like above as need

Foo<T>::setValue签名随后变为:

Foo& setValue(const typename Ref_or_Value<T>::type other);

无论这是否过分,我都会让你决定,但这应该让setValue做"正确的事情"。如果是T=int,则setValue将按值接受参数。如果T=Foobar_object,那么它将通过常量引用。

在Visual Studio 2010上不会对我产生任何警告/错误。非常奇怪的是,你的编译器显示了诊断,因为这是没有意义的。3是一个右值,并且明确允许右值绑定到像const int&这样的常量引用。

相关文章:
  • 没有找到相关文章