为什么make_optial会衰减其参数类型
Why does make_optional decay its argument type?
(可能不是C++14,可能是库TS(设施make_optional
(在n3672中(定义为:
template <class T>
constexpr optional<typename decay<T>::type> make_optional(T&& v) {
return optional<typename decay<T>::type>(std::forward<T>(v));
}
为什么有必要转换类型T
(即不只是返回optional<T>
(,是否有哲学(以及实践(理由专门使用decay
作为转换?
decay
的一个通用目的是获取一个类型并将其修改为适合存储。
看看这些例子,decay
可以工作,而remove_reference
不会:
auto foo( std::string const& s ) {
if (global_condition)
return make_optional( s );
else
return {};
}
或
void function() { std::cout << "hello world!n"; }
auto bar() { return std::make_optional( function ); }
或
int buff[15];
auto baz() { return std::make_optional( buff ); }
optional<int[15]>
将是一个非常奇怪的野兽——C风格的数组在像文字一样处理时表现不佳,这就是optional
对其参数T
所做的。
如果要复制数据,则源的const
或volatile
性质无关紧要。并且,您只能通过将数组和函数衰减为指针来制作数组和函数的简单副本(而不需要回退到std::array
或类似内容(。(理论上,optional<int[15]>
可以工作,但这会带来很多额外的复杂性(
所以std::decay
解决了所有这些问题,并且不会真正引起问题,只要允许make_optional
推导其参数的类型,而不是从字面上传递T
。
如果你想从字面上传递一个T
,那么根本没有理由使用make_optional
。
这不是make_optional
的新行为;实用函数CCD_ 21和CCD_。我可以看到至少两个这样做的原因:
-
使用未更改的类型实际实例化模板可能是不可取的,也可能是不可能的。
-
如果
T
是一个函数类型,那么,您就不能将函数存储在类、句点中;但是可以存储函数指针(衰退类型(。 -
如果
T
是一个数组类型:由于数组是不可复制赋值的,因此生成的类将是"有缺陷的",因为它无法复制。对于optional
,根本无法编译value_or
成员函数,因为它返回T
。因此,optional
中根本不能有数组类型。
-
-
不衰减类型可能会导致意外行为。
-
如果参数是字符串文字,我个人希望包含的类型是
const char*
,而不是const char [n]
。这种衰变发生在大多数地方,为什么不在这里呢? -
如果
v
是左值,则T
将被推导为左值参考类型。我真的想要一个包含引用的对吗,例如,仅仅因为其中一个参数是左值?当然不是。 -
对或元组内的类型或可选类型或其他不应获得
v
的cv资格的类型。也就是说,假设我们将x
声明为const int
。make_optional(x)
应该创建optional<const int>
吗?不,不应该;它应该创建CCD_ 38。
-
看看decay
的作用:
-
删除引用限定符--
T&
→T
;没有可选的引用,否则您无法重新放置optional
,它需要是可分配的。 -
对于数组类型,删除范围--
T[42]
→T*
;可选的固定范围数组没有那么有用,因为每个数组大小都有不同的类型,并且不能直接按值传递数组类型,这是value
和value_or
成员函数工作所必需的。 -
对于函数类型,添加指针--
T(U)
→T(*)(U)
;由于类似的原因,没有可选的函数引用。 -
否则,删除cv限定符--
const int
→int
;没有可选的const
值,否则无法重新设置optional
。
- 扩展C++生成的代码的模板参数类型名称
- 如何在 c++ 中定义接受不同参数类型的函数向量?
- 在 C++ 中运行时调用模板时,是否可以切换模板的参数类型?
- 将函数参数类型声明为 auto
- 将函数的参数 - 签名从使用 'std::function<T>' 转换为模板参数类型
- 在 C++17 中调用具有不同参数类型的构造函数
- 具有先前参数类型匹配的参数包
- 我想知道为什么"std::unique_ptr<int> foo(新 int)"是合法的,因为"std::<int>unique_ptr"要求输入参数类型应该是"int"?
- 将可变参数类型列表的扩展打包为复杂类型的初始值设定项列表 - 合法吗?
- MSVC 错误:4 个重载中的任何一个都无法转换所有参数类型
- 使用constexpr + auto作为返回和参数类型的奇怪类型推导
- 如何从第一个参数推断第二个参数类型?
- C++模板函数中,指定回调函子/lambda 的参数类型,同时仍允许内联?
- 如何用不同的参数类型和数字回调函数
- C++stoi:这两个重载都无法转换所有参数类型
- 为什么std::{container}::template不能推导其参数类型
- 为模板参数类型中的新对象分配内存
- 为指向成员模板参数的指针推导额外模板参数类型的紧凑方式
- 使用std::conditional中的模板来确定函数参数类型
- C++中的短参数类型