2016-08-01 79 views
5

我有一个看似简单的问题,我不知道如何解决。模板重载(参考和非参考版本)

想象一下下面的模板方法

template<typename T> void Add(T& var); 

,其中特可以添加东西的容器(排序)。我可以通过POD或更复杂的类型,如strings,这就是为什么我通过T作为参考。

这样做的问题是,每当我想打电话给加入(...)用像另一个方法的结果:

Add(MethodThatReturnsAnInt()); 

这将无法正常工作和临时变量是需要保持结果MethodThatReturnsAnInt()

是否有任何方式重载Add,以便我可以有一个引用传递和非引用传递版本?

template<typename T> void Add(T& var); 
template<typename T> void Add(T var); 

std::enable_if在这种情况下有什么用?

+0

阅读并了解[右值引用](http://en.cppreference.com/w/cpp/language/reference)。 –

+0

Google _forwarding reference_。你的情况和由此产生的问题非常普遍,他们添加了一个语言功能。 ;-)这是C++ 11的一个基本特性,可能已经足够的时间了。 –

+0

你真的想解决什么问题? Add()有什么作用? – Barry

回答

6

如果你有一个C++编译器11,你可以使用一个(Universal Reference)转发参考

template<typename T> void Add(T&& var) {} 

int MethodThatReturnsAnInt() { return 42; } 

int main() 
{ 
    int a = MethodThatReturnsAnInt(); 

    Add(a);      // lvalue passed: void Add(int& var) takes lvalue reference 
    Add(MethodThatReturnsAnInt()); // rvalue passed: void Add(int&& var) takes rvalue reference 
} 

T&&是不是在这个例子中右值引用。在类型推断的情况下,T&&具有特殊的含义。 T取决于传递给函数Add()表达式如下:

  • 如果表达式为左值E型的(例如a),则T被推断为E&

  • 如果表达式为右值E型的(例如由函数返回值),则T被推断为Evar将具有类型E&&

+0

这与@SamVarshavchik说的有什么不同(除了您使用的是旧式名称_universal reference_)?此外,这个例子看起来有些错误和误导。 – skypjack

+0

第二个调用实际上是'Add(int && var)',而不是'Add(int var)'。 'int'可能是相同的,但不适用于更复杂的类。 – Holt

+2

@skypjack sam name放弃了您可以用于google的术语,并在其他地方使用帮助来解决问题。 Sergji发布了一个解决此问题的答案。 – Yakk

2

如果您的编译器尚不支持C++ 11,则需要更新编译器,然后使用转发参考&&