标准::make_pair类型扣除
std::make_pair type deduction
我遇到了一些奇怪的事情,我想解释一下。以下代码片段提供了一个简单的类模板type
和两个operator<<
:一个用于type
的专用化,另一个用于type
专用化的std::pair
。
#include <ostream>
#include <utility>
template <typename T>
class type {
public:
T value_;
};
template <typename CTy, typename CTr, typename T>
std::basic_ostream<CTy,CTr>&
operator<<(std::basic_ostream<CTy,CTr>& os, type<T> const& a)
{
return os << a.value_;
}
template <typename CTy, typename CTr, typename T>
std::basic_ostream<CTy,CTr>&
operator<<(std::basic_ostream<CTy,CTr>& os, std::pair<T const, T const> const& a)
{
return os << a.first << ',' << a.second;
}
#include <iostream>
int
main()
{
using float_type = type<float>;
float_type const a = { 3.14159 };
float_type const b = { 2.71828 };
#if 0
std::cout << std::make_pair(a, b)
<< std::endl;
#else
std::cout << std::pair<float_type const, float_type const>(a, b)
<< std::endl;
#endif
}
main
函数提供专用化和该专用化的两个变量。有两种变体可以将变量显示为std::pair
。第一个失败是因为std::make_pair
似乎从变量中剥离了const
说明符,这反过来又与第二个operator<<
的签名不匹配:std::pair<T const, T const>
。然而,构建一个std::pair
专业化(main
中的第二行std::cout
)以及从std::pair
operator<<
中删除T
的const
规范是有效的,即std::pair<T, T>
.
编译器消息:
海湾合作委员会 4.9.2
std_make_pair.cpp: In function 'int main()': std_make_pair.cpp:52:35: error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&' std::cout << std::make_pair(a, b) << std::endl; ^ In file included from std_make_pair.cpp:3:0: /usr/include/c++/4.9.2/ostream:602:5: note: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = std::pair<type<float>, type<float> >]' operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x) ^
clang 3.5(删除了系统标头中的不可行函数)
std_make_pair.cpp:52:13: error: invalid operands to binary expression ('ostream' (aka 'basic_ostream<char>') and 'pair<typename __decay_and_strip<const type<float> &>::__type, typename __decay_and_strip<const type<float> &>::__type>') std::cout << std::make_pair(a, b) << std::endl; ~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~ std_make_pair.cpp:30:1: note: candidate template ignored: can't deduce a type for 'T' which would make 'const T' equal 'type<float>' operator<<(std::basic_ostream<CTy,CTr>& os, std::pair<T const, T const> const& a)
所以,这里有一个问题:我是否应该指定一个operator<<
采取T
std::pair
而不是T const
?这不是淡化我与任何功能用户建立的合同,即我基本上承诺只以非变异方式使用T
T const
吗?
第一个失败
std::make_pair
因为它似乎从变量中剥离了 const 说明符,这反过来又与第二个operator<<: std::pair<T const, T const>
的签名不匹配
这是正确的。make_pair
是一个函数模板,它依赖于std::decay
显式删除const
、volatile
和&
限定符:
template <class T1, class T2> constexpr pair<V1, V2> make_pair(T1&& x, T2&& y);
回报:
pair<V1, V2>(std::forward<T1>(x), std::forward<T2>(y));
其中V1
和V2
确定如下:让每个Ti
Ui
decay_t<Ti>
。那么如果Ui
等于reference_wrapper<X>
,则每个Vi
X&
,否则Vi
Ui
。
编译器拒绝您的代码是完全正确的 - 您为pair<const T, const T>
添加了流运算符,但正在尝试流式传输pair<T, T>
。解决方案是删除流运算符中额外的const
要求。该函数中的任何内容都不要求pair
由const
类型组成 - 只是类型本身是可流式传输的,这与它们的const
性无关。这没有错:
template <typename CTy, typename CTr, typename T>
std::basic_ostream<CTy,CTr>&
operator<<(std::basic_ostream<CTy,CTr>& os, std::pair<T, T> const& a)
{
return os << a.first << ',' << a.second;
}
您已经通过引用 const 来获取pair
,无论如何您都无法修改其内容。
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 大量序列中核苷酸类型的快速计数
- 如何从C++中的依赖类型中获得它所依赖的类型
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如何获取std::result_of函数的返回类型
- 从父命名空间重载类型
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 访问者访问变体并返回不同类型时出错
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 模板元程序查找相似的连续类型名称
- 是否可以从int转换为enum类类型
- 使用 make 编译 MPI,几个命名空间错误,例如"错误:未知类型名称'使用'?
- 尝试在Linux Mint 17.1 64位上"make" C++项目时从cstdlib和类似内容编译错误(未声明/不是类型)
- 如何使用Make以相同的方式编译多个文件类型