[英]Const temporary from template type and why use std::add_const?
[英]Use cases for std::add_const and similar
<type_traits>
某些类型转换也可以使用核心语言语法来表示(例如std::add_const<T>::type
is /似乎与const T
等效)。 Dtto代表std::add_lvalue_reference
,也许还有其他。 这些类型特征有什么用?
我完全理解该标准将在没有它们的情况下提供“不完整的工具箱”,并且我可以想象以元方式使用,如下所示:
template<typename In, template <typename> class Modifier>
struct Apply {
typedef typename Modifier<T>::type Out;
};
Apply<int, std::add_const>
这些特性是否还有其他用例可以用句法表达,或者只是出于“完整感”而包括在内,还是偶尔用于元使用?
这些特性来自Boost以及将其添加到标准N1345中的提议 ,引用了Andrei Alexandrescu的话:
“我理解添加
add_const
,add_volatile
,add_cv
和add_pointer
,但是我主张消除它们。语言提供的等效项只是更简单,更好。”
相同的建议也给出了以下理由:
作者的注释:从表面上讲,add_const,add_volatile和add_cv类无关紧要,因为,例如,对于所有T,add_const :: type与T const相同(当前不适用于函数类型-但问题295解决了此问题 )。 但是,boost的经验是,由于以下原因,一些用户要求这些模板出现在库中:(a)一些用户发现这些模板更明确-特别是在组合转换模板时,用户喜欢“内置”这些模板提供的“文档”。 (b)并非所有用户都知道允许cv限定引用是无效的,或者不允许cv限定已经是cv限定的类型,并且无效。 (c)当cv限定作为引用的类型或已经具有cv限定符的类型时,编译器可能会发出警告,可以实现这些模板,以便在这些情况下禁止显示这些消息。
另外,对于add_reference
(在标准中重命名为add_lvalue_reference
):
作者的注释:add_reference模板是boost类型特征库背后的原始动机之一。 但是, 发布106的决议使模板看起来在很大程度上是多余的。 尽管如此,当在模板代码中无意中创建对引用的引用时,add_reference可能在抑制编译器警告方面很有用。
这些特征仅供偶尔使用。 这使得在元编程中传输所需的cv限定词成为可能。
template<class T,template<class> class Trait>
struct transform
{
/* working with T creating newT*/
typedef Trait<newT>::type type;
};
template<class T>
struct special_transform
: transfrom<T, std::add_const>
{};
在这种情况下,您无法将std::add_const
替换为const
。
add_const
可用于解决类型推导冲突。
template <typename T>
class wrapper;
template <typename T>
bool operator==(wrapper<T> const& w, T const& t);
如果使用wrapper<T const>
则会出现问题:
wrapper<int const> w = { 42 };
assert(w == 42); // Error: conflicting deduced types
T
同时被推导为int
和 int const
。 可以使用add_const
解决:
template <typename T>
bool operator==(wrapper<T> const& w, add_const_t<T>& t);
我知道的唯一用例如下所示:
struct F
{
bool f() const { return true; }
bool f() { return false; }
};
assert(!F{}.f())
assert(std::add_const_t< F >{}.f());
还需要测试cv-ref合格的成员函数的功能,这可能因不同的重载而有所不同(仅对于lref合格的现代C ++具有方便的std::as_const
函数):
struct F
{
int g() & { return 1; }
int g() const & { return 2; }
int g() && { return 3; }
int g() const && { return 4; }
};
F f;
assert(f.g() == 1);
assert(std::as_const(f).g() == 2);
assert(F{}.g() == 3);
assert(std::add_const_t< F >{}.g() == 4); // rarely needed, but if needed, then it helps
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.