【发布时间】:2015-06-03 23:40:45
【问题描述】:
假设您正在为客户端库提供具有多个引用参数的函数。
为了简单起见,假设我们有 3 个参数,它们是对 int 的各种引用(因此您可以假设这些常量也将由 initializer_list 创建)。
应该可以从调用站点将临时创建的常量(右值)传递给函数(在这种情况下考虑测试代码)以及对另一个实体拥有的对象的真实引用。
到目前为止,我提出了以下解决方案:
void bar(int &x, int &y, int &z) { }
// use a template wrapper to turn rvalues into lvalues.
template <typename T, typename U, typename V>
void foo(T &&t, U &&u, V &&v) {
bar(t,u,v);
}
// create a humongous amount of overloads
void baz(int &&x, int &y, int &z) { }
void baz(int &x, int &&y, int &z) { }
void baz(int &&x, int &&y, int &z) { }
void baz(int &x, int &y, int &&z) { }
void baz(int &&x, int &y, int &&z) { }
void baz(int &x, int &&y, int &&z) { }
void baz(int &&x, int &&y, int &&z) { }
// claim ownership of the objects and create temporaries
void bam(int x, int y, int z) { }
int main() {
int i = 1;
foo(i,2,3);
foo(2,i,3);
foo(2,3,i);
bar(i,2,3); // doesn't compile
bar(2,i,3);
bar(2,3,i);
baz(i,2,3); // requires 8 overloads
baz(2,i,3);
baz(2,3,i);
return 0;
}
我对所有解决方案并不完全满意,因为它们中的每一个都有缺点。有没有更清洁的方法来解决这个问题?
【问题讨论】:
-
我只会默认使用 C++03
const&,除非分析器显示出为给定用例添加 rref 重载的一些巨大优势。 -
这是完美的转发问题。规范的解决方案是直接(通用引用和 srtd::forward)或间接(按值传递)使用右值引用。你说的缺点是什么?当然,用
int来说明是个坏主意。 (注意:您的模板包装器解决方案不正确,因为您缺少 std::forward。) -
@Pradhan 我特别不想在示例中使用
map<string, vector<boost::variant<X,Y,Z>>。缺点在于 cmets。到目前为止,我有一个标准的可变参数模板函数,我在这种情况下粘贴了它,它会慢慢地乱扔我的源代码。复制大的东西不是我想要的方式,也会造成很多重载。 -
@Alex 您能否为传递值和“通用参考”模板解决方案添加 cmets?此信息将有助于回答您的具体问题。
-
@Alex 你没有提到最明显的解决方案
void qux(int const &x, int const &y, int const &z) { }。所以我猜你有一些想法,你可能希望参数是可变的,但这与bar(i,2,3)不相符,因为2是不可变的。因此,您需要明确描述该函数的输入条件和行为。
标签: c++ c++11 rvalue-reference