C++ 模板:使用常量参数自动重载 const&模板化函数?
C++ Templates: Automatically overload templated function with const& for constant params?
假设我有一个模板函数foo(),它将两个整数引用作为参数。我希望template函数也能自动处理常量引用(比如来自常量的引用)。下面是一个概括的例子。我可以让foo()工作,但我必须为引用/常量引用参数的每个排列提供一个新的实现。
#include <iostream>
using namespace std;
template<typename A, typename B>
void foo(A& a, B& b)
{
cout<<"a:"<<a<<" b:"<<b<<endl;
}
template<typename A, typename B>
void foo(A& a, const B& b)
{
cout<<"a:"<<a<<" b:"<<b<<endl;
}
template<typename A, typename B>
void foo(const A& a, B& b)
{
cout<<"a:"<<a<<" b:"<<b<<endl;
}
template<typename A, typename B>
void foo(const A& a, const B& b)
{
cout<<"a:"<<a<<" b:"<<b<<endl;
}
int main()
{
int x = 0;
foo(x, x);
foo(x, 10);
foo(10, x);
foo(20, 20);
return 0;
}
上面的例子有点做作,但它是我试图做的事情的概括。在我更复杂的情况下,我有一个类,它充当一组参数的包装器。类构造函数是模板化的,就像foo()一样,可以有多达10个参数。列举所有2^10个可能的构造函数将是一场噩梦。
您描述的问题是完美转发问题。C++11用通用引用解决了这个问题:
template<typename A, typename B>
void foo(A&& a, B&& b) {
bar(std::forward<A>(a), std::forward<B>(b));
}
这里的参数不是右值引用,而是通用引用。它们将具有与自变量相同的引用性和const性。
如果参数是右值,那么在foo
中,参数将是带名称的右值。命名右值是左值。要将参数传递给具有保留值的子函数,需要将它们封装在std::forward
中。函数bar
将得到与foo
类型完全相同的a
和b
。
如果模板不打算修改参数,那么只需提供带有const&
的版本就可以了:
template<typename A, typename B>
void foo(const A& a, const B& b)
{
cout<<"a:"<<a<<" b:"<<b<<endl;
}
如果您传递一个非常量左值,它仍然会被一个常量引用绑定,一切都会正常工作。
如果你想让一些重载修改参数,那么重新考虑设计,因为这些函数似乎不应该共享一个名称。也有例外,例如,结构内部成员的访问器,如果对象是const
,则可能需要返回const&
,否则可能需要返回非常数引用。。。如果是这样的话,你可以走相反的路,只提供非常重载:
template<typename A, typename B>
void foo(A& a, B& b)
在这种情况下,如果参数是临时引用或非常数引用,则推导类型将反映它,并将参数与const&
绑定。
int main() {
int a = 5;
const int b = 10;
foo(a,b); // foo<int,const int>(int&,const int&)
foo(10,b); // foo<const int,const int>(const int&, const int&)
}
重读你的问题,你可能会对完美转发感兴趣(这可能符合你的要求,也可能不符合你的意愿)。如果是这样的话,如果你有一个C++11编译器,你可以使用带有可变模板的通用引用。构建一个好的包装器是一件困难的事情,尽管您可以只使用std::tuple
作为实际的存储,这应该会使任务变得非常简单。
除了发布的所有正确答案外,这里还有一个简单的程序供您参考,因为这可能会帮助您更好地理解这个概念。
#include<iostream>
template<class X>
void func(X& x, X& y)
{
//your code
}
template<class X, class Y>
void intermediateFunc(X&& x, Y&& y)
{
func(x,y);
}
int main()
{
int y = 9;
intermediateFunc(5,5);
intermediateFunc(y,5);
intermediateFunc(5,y);
intermediateFunc(y,y);
}
- 在 const 函数中通过引用和指针返回之间的区别
- 使用 std::string () const 函数启动线程或未来
- 如果我在 const 函数上使用指针,我可以返回什么?
- 为什么 const 函数返回左值而不是右值?
- 当我调用 main 中使用 const 对象的 const 函数时,不断出现错误
- 在 const 对象上调用非 const 函数
- 析构函数是否可以在 const 对象上调用非 const 函数
- C/C++ 如何在一次函数调用中交出 const 函数指针或简单指针
- 为什么我可以在C 11中使用const函数修改类
- 防止const函数被调用非const对象
- 如果C 中的支架重载运算符被声明为const函数
- C++:防止在 const 函数中更改指针的值
- 从const函数返回非const属性参考
- 调用指针参数从const函数指向的对象的操作员
- 在const函数中调用非CONST成员的非const函数
- 无法将 const 数据类型传递到非 const 函数中
- 这是检查 const 函数(如果是否创建某些内容)的更好方法
- 在 const 函数中从地图中未经选中读取
- 编译器不会为 "const" 和"not-const"函数给出不明确的错误吗
- 通过const函数中的参数索引返回std :: map的值