C++:将引用类型显式指定为类型参数的模板函数
C++: template function with explicitly specified reference type as type parameter
我正在玩C++模板类型推导,并设法编译了这个小程序。
template<typename T>
void f(const T& val)
{
val = 1;
}
int main()
{
int i = 0;
f<int&>(i);
}
它可以在所有主要编译器上编译,但我不明白为什么。为什么f
可以分配给val
,当val
被明确标记为const
时?是这些编译器中的错误还是根据C++标准的有效行为?
§8.3.2 [dcl.ref]/p6:
如果是 typedef-name (7.1.3, 14.1(* 或 decltype-specifier (7.1.6.2( 表示类型 TR,它是对类型 T 的引用,尝试 创建类型"对 cv TR 的左值引用"创建类型"左值" 引用 T",同时尝试创建类型"右值引用" 到 cv TR"创建类型 TR。
这称为引用折叠,并在 C++11 中引入。在 C++03 中,您的代码格式不正确,但一些编译器支持将其作为扩展。
注意,在const T &
中,const
适用于类型T
,所以当T
int &
时,const
将应用于引用类型本身(这是没有意义的,因为引用无论如何都是不可变的(,而不是引用的类型。这就是为什么参考折叠规范忽略TR
上的任何 cv 限定符。
*模板类型参数是 typedef 名称,根据 §14.1 [temp.param]/p3:
标识符不跟在省略号后面的类型参数 将其标识符定义为 typedef-name(如果声明为
class
或typename
(或模板名称(如果声明为template
( 在模板声明的范围内。
帖子中引用以下来自C++标准(8.3.2 参考文献(
1... Cv 限定引用的格式不正确,除非通过使用 typedef-name (7.1.3, 14.1( 或特定于 decltype 的 (7.1.6.2(,在这种情况下,将忽略 cv 限定符。
[ Example:
typedef int& A;
const A aref = 3; // ill-formed; lvalue reference to non-const initialized with rvalue
在上面来自 C++ 标准的示例中,最后一个语句不会被编译,因为限定符 const 被忽略(根据引用(,并且您不能将右值与非 const 引用绑定。
const T&
在此示例中不会变成int&
:在f<int&>(i)
中,您将T
显式设置为int&
。 只有当T
的定义用于确定val
的类型时,const
才会进入图片,这变得const int&
(一个微妙之处是引用在此替换过程中折叠,因此您不会在类型中出现两个&
(。
- 在 c++ 中的模板实例化中使用带有构造函数的类作为类型参数
- 如何在 c++ 中定义接受不同参数类型的函数向量?
- 函数类型参数的模板参数推导
- 基于类型作为参数的字符串表示形式具有不同返回类型的函数
- PowerShell 使用结构类型参数调用 C++ DLL 的导出函数
- 通过引用传递参数;函数返回类型是否必须为 VOID?
- 参数数据类型未知的可变参数函数
- 使用其他模板类型参数作为要在函数签名中使用的类型别名声明
- 如何避免具有相同类型参数的函数中的错误
- 将内置类型变量传递给只有一个类类型参数的"+"运算符函数时自动类型转换的构造函数
- 使用返回不完整类型的函数作为默认参数
- 迭代器的模板参数:函数在调用时推断类型?
- EXPECT_CALL具有 unique_ptr 引用类型参数的模拟函数
- 是否可以使用泛型枚举类型作为函数的参数?
- 如何动态加载和调用具有特定于库的类型作为函数参数的符号
- SFINAE 和模板函数实例化:为什么在启用了 SFINAE 类型的函数参数中使用模板参数时无法推断模板参数?
- 使用模板将任意类型参数传递给 C++ 中的函数
- 具有可变参数类型参数的可变参数函数
- C++ 如何将参数绑定到具有相同返回类型的函数,并将它们全部存储在一个容器中
- 具有非模板类型参数的模板函数的重载解析