2011-05-18 109 views
2

传递引用函数如何区分传递值函数?例如:区分传递引用和传递值

template <typename T> 
void sort(std::vector<T>& source); // Sorts source. 

// Versus... 

template <typename T> 
std::vector<T> sort(std::vector<T> source); // Returns a sorted copy of source. 

这两个函数是不明确的;其中一个必须重新命名或完全删除。

如何避免这种情况?一种形式是否应该优先于其他形式?或者是否有任何通用的命名指南来区分它们?

+1

为什么这是一个需要解决的问题?由于它们不明确,编译器不会允许它们共存,因此只要运行编译器,问题就会持续下去,之后程序员将撤销先前的更改。 – 2011-05-18 17:07:44

+0

这是一个关于函数签名的问题。如果第二个声明通过'const'引用传递,则编译器可以区分签名。 – 2011-05-18 17:11:55

+0

是否真的不可能在调用时区分OP问题中的两个函数?如果是的话,如果没有,如果C++编译器提供了一个错误,即使函数没有被调用,它也不会是稍微好一点的行为吗?我可以在没有调用的情况下使用gcc 4.6.3进行编译。 – 2013-01-08 17:34:46

回答

6

难道你不能给他们不同的名字吗?例如,我会命名功能版本sorted

只是因为你可以重载函数(或函数模板在这种情况下)并不意味着你来。

顺便说一句,你可以实现的“势在必行版”术语“功能版本”:

template <typename T> 
void sort(std::vector<T>& source) 
{ 
    // sort in place 
} 

template <typename T> 
std::vector<T> sorted(std::vector<T> copy) 
{ 
    sort(copy); 
    return copy; 
} 
+5

“仅仅因为你可以超载并不意味着你应该”是黄金。 – 2011-05-18 17:03:19

0

它通常倾向于不通过非const引用如果可能的话,并使用第二通形成。这是因为首先,如果要将返回值传递给另一个函数,则第二类播放会更好,其次,因为编译器的优化器将在大多数情况下处理不必要的复制;第三,因为有参考可以防止任何类型的TMP检测到它实际上是一个返回值,并阻止在任何类型的函数对象上下文中使用该函数。

+0

Downvoter评论? – GManNickG 2011-05-18 19:34:02

+1

@GMan:不是我的downvote,但1)“防止在任何类型的函数对象上下文中使用函数”是错误的(例如std :: for_each),2)典型的使用名为sort的函数(例如std :: sort,boost :: sort)是引用语义而不是价值语义,3)并没有解决有利于模糊泛型建议的问题,而这些建议又与“排序”约定背道而驰。似乎这应该是一个评论。 – 2011-05-19 01:41:28

2

FredOverflow击中了头部。但是,要回答你的问题“或者是否有任何通用的命名指南来区分它们?”只要确保你是一致的。例如你的例子中的第二个函数名称就像SortCopy。 SortCopy,SortCpy,Sort_Copy无关紧要。重要的是,在整个代码中,你是一致的(例如,所有作用于副本的函数都有“Copy”前缀 - 没有一个具有Copy,下一个Cpy等)。

+2

+1就是C++库所做的事情:'std :: reverse()'/'std :: reverse_copy()','std :: remove_if()'/'std :: remove_copy_if()'boost boost'boost :: to_lower()'/'的boost :: to_lower_copy()' – Cubbi 2011-05-18 17:55:33