来自引用包装器的 Const 引用包装器
Const reference wrapper from reference wrapper
考虑以下参考包装器:
template <class T>
struct wrapper
{
wrapper(T& x): reference{x} {}
void set(const T& x) {reference = x;}
T& get() const {return reference;}
T& reference;
};
我在想:
- 如何仅通过模板别名声明 const 引用包装器
template <class T> using const_wrapper = /* const wrapper<T> or wrapper<const T>?*/
- 如果在此状态下不可能,如何更改包装器结构以使前面的点成为可能?
- 如何解决以下问题:
int i = 42; wrapper<const char> w(i);
可以编译但无法运行(我想阻止构造函数)
- 具体是什么问题,
iterator
和const_iterator
一般有两种不同的实现方式?
How to declare a const reference wrapper through a template alias only template <class T> using const_wrapper = /* const wrapper<T> or wrapper<const T>?*/
显然是:
template <class T> using const_wrapper = wrapper<const T>;
包含的类型是 const
,不是包装器。
但是请注意,如果 T
为 const
,则无法调用您的 set
函数。这是出于显而易见的原因;您无法更改 const
值。
How to solve the following problem: int i = 42; wrapper<const char> w(i);
will compile but not work (I would like to block the constructor)
这个其实有点复杂。如果用户尝试使用与 T
不完全匹配的类型,您要做的就是导致编译失败。为此,您需要使用 C++11 的 =delete
功能:
template <class T>
struct wrapper
{
wrapper(T& x): reference{x} {}
template<typename U>
wrapper(const U &) = delete;
//...
};
当任何人传递的类型与 T
不完全匹配时,将使用第二个构造函数。由于它是 delete
d,因此当人们尝试使用它时会出现编译器错误。
For what exact problem, iterator and const_iterator general have two different implementations?
谁说的?它们甚至不需要是 不同的 类型(例如考虑 set
的迭代器),更不用说需要有不同的 实现 .它们只是不同的类型别名。
假设 set
应该更改引用对象的值而不是引用本身:
template <class T>
struct wrapper
{
wrapper(T& x) : reference{ x } {}
template<typename U>
wrapper(U& x) : reference{ x } {} //<- Possible answer for question 3
//template<typename U>
//wrapper(U& x) = delete; //<- Possible answer for question 3
void set(const T& x) const { reference = x; } //<- Answer for question 2
T& get() const { return reference; }
T& reference;
};
template <class T>
using const_wrapper = const wrapper<T>; //<- Answer for question 1
int main()
{
//Testing const_wrapper
char a;
const_wrapper<char> b(a);
b.set('a');
//Testing narrowing cast
int i = 42;
wrapper<const char> w(i); //error C2397: conversion from 'int' to 'const char' requires a narrowing conversion
//error C2280 : 'wrapper<const char>::wrapper<int>(U &)' : attempting to reference a deleted function
//w.set('b'); //error C3490: 'reference' cannot be modified because it is being accessed through a const object
}
关于你最后一个问题,我无法给你一个满意的答案。这几乎是一个实现细节。 我想不出 iterator
和 const_iterator
至少没有相互继承的任何一般情况 - 非 const 版本扩展了 const 版本。
更新: 最后一部分可能是 MSVC 特定的实现细节。我仍然认为从 const_iterator
继承 iterator
是合理的,但应该指出这一点。
- How to declare a const reference wrapper through a template alias only
template <class T> using const_wrapper = /* const wrapper<T> or wrapper<const T>?*/
这取决于你想要表达的意思,你没有说清楚。
- How to change the wrapper struct to make the preceding point possible if it is not possible in this state?
见上文。
- How to solve the following problem:
int i = 42; wrapper<const char> w(i);
will compile but not work (I would like to block the constructor)
添加部分专业化
template <class T>
struct wrapper<const T>
{
wrapper(const T& x): reference{x} {}
wrapper(T&) = delete;
void set(const T& x) {reference = x;}
const T& get() const {return reference;}
const T& reference;
};
或者向主模板添加适当约束的构造函数:
template <class T>
struct wrapper
{
wrapper(T& x): reference{x} {}
template<typename U, typename = std::enable_if_t<std::is_const<T>{} && std::is_same<T, const U>{}, void>>
wrapper(U&) = delete;
void set(const T& x) {reference = x;}
T& get() const {return reference;}
T& reference;
};
- For what exact problem,
iterator
and const_iterator
general have two different implementations?
通常应该可以将 iterator
隐式转换为 const_iterator
但反之则不行。因此,您要么需要一个仅适用于 const_iterator
形式的 SFINAEd 构造函数,要么您有两种实现,一种支持额外转换,另一种不支持。
使用 SFINAE 在 C++98 中不是一个选项,因此大多数标准库实现(在 Expression SFINAE 可用之前很久就编写了)使用两个单独的实现。
考虑以下参考包装器:
template <class T>
struct wrapper
{
wrapper(T& x): reference{x} {}
void set(const T& x) {reference = x;}
T& get() const {return reference;}
T& reference;
};
我在想:
- 如何仅通过模板别名声明 const 引用包装器
template <class T> using const_wrapper = /* const wrapper<T> or wrapper<const T>?*/
- 如果在此状态下不可能,如何更改包装器结构以使前面的点成为可能?
- 如何解决以下问题:
int i = 42; wrapper<const char> w(i);
可以编译但无法运行(我想阻止构造函数) - 具体是什么问题,
iterator
和const_iterator
一般有两种不同的实现方式?
How to declare a const reference wrapper through a template alias only template
<class T> using const_wrapper = /* const wrapper<T> or wrapper<const T>?*/
显然是:
template <class T> using const_wrapper = wrapper<const T>;
包含的类型是 const
,不是包装器。
但是请注意,如果 T
为 const
,则无法调用您的 set
函数。这是出于显而易见的原因;您无法更改 const
值。
How to solve the following problem:
int i = 42; wrapper<const char> w(i);
will compile but not work (I would like to block the constructor)
这个其实有点复杂。如果用户尝试使用与 T
不完全匹配的类型,您要做的就是导致编译失败。为此,您需要使用 C++11 的 =delete
功能:
template <class T>
struct wrapper
{
wrapper(T& x): reference{x} {}
template<typename U>
wrapper(const U &) = delete;
//...
};
当任何人传递的类型与 T
不完全匹配时,将使用第二个构造函数。由于它是 delete
d,因此当人们尝试使用它时会出现编译器错误。
For what exact problem, iterator and const_iterator general have two different implementations?
谁说的?它们甚至不需要是 不同的 类型(例如考虑 set
的迭代器),更不用说需要有不同的 实现 .它们只是不同的类型别名。
假设 set
应该更改引用对象的值而不是引用本身:
template <class T>
struct wrapper
{
wrapper(T& x) : reference{ x } {}
template<typename U>
wrapper(U& x) : reference{ x } {} //<- Possible answer for question 3
//template<typename U>
//wrapper(U& x) = delete; //<- Possible answer for question 3
void set(const T& x) const { reference = x; } //<- Answer for question 2
T& get() const { return reference; }
T& reference;
};
template <class T>
using const_wrapper = const wrapper<T>; //<- Answer for question 1
int main()
{
//Testing const_wrapper
char a;
const_wrapper<char> b(a);
b.set('a');
//Testing narrowing cast
int i = 42;
wrapper<const char> w(i); //error C2397: conversion from 'int' to 'const char' requires a narrowing conversion
//error C2280 : 'wrapper<const char>::wrapper<int>(U &)' : attempting to reference a deleted function
//w.set('b'); //error C3490: 'reference' cannot be modified because it is being accessed through a const object
}
关于你最后一个问题,我无法给你一个满意的答案。这几乎是一个实现细节。 我想不出 iterator
和 const_iterator
至少没有相互继承的任何一般情况 - 非 const 版本扩展了 const 版本。
更新: 最后一部分可能是 MSVC 特定的实现细节。我仍然认为从 const_iterator
继承 iterator
是合理的,但应该指出这一点。
- How to declare a const reference wrapper through a template alias only
template <class T> using const_wrapper = /* const wrapper<T> or wrapper<const T>?*/
这取决于你想要表达的意思,你没有说清楚。
- How to change the wrapper struct to make the preceding point possible if it is not possible in this state?
见上文。
- How to solve the following problem:
int i = 42; wrapper<const char> w(i);
will compile but not work (I would like to block the constructor)
添加部分专业化
template <class T>
struct wrapper<const T>
{
wrapper(const T& x): reference{x} {}
wrapper(T&) = delete;
void set(const T& x) {reference = x;}
const T& get() const {return reference;}
const T& reference;
};
或者向主模板添加适当约束的构造函数:
template <class T>
struct wrapper
{
wrapper(T& x): reference{x} {}
template<typename U, typename = std::enable_if_t<std::is_const<T>{} && std::is_same<T, const U>{}, void>>
wrapper(U&) = delete;
void set(const T& x) {reference = x;}
T& get() const {return reference;}
T& reference;
};
- For what exact problem,
iterator
andconst_iterator
general have two different implementations?
通常应该可以将 iterator
隐式转换为 const_iterator
但反之则不行。因此,您要么需要一个仅适用于 const_iterator
形式的 SFINAEd 构造函数,要么您有两种实现,一种支持额外转换,另一种不支持。
使用 SFINAE 在 C++98 中不是一个选项,因此大多数标准库实现(在 Expression SFINAE 可用之前很久就编写了)使用两个单独的实现。