其思想是您可以有一个名为maybe的简单类型,它包装了另一个类型,它提供了不可能从函数返回值的能力。我肯定它还不完美,但它有我正在寻找的广泛的打击。我主要是在找我漏掉的案子,还有其他我忽略的东西。
#ifndef MAYBE_H_
#define MAYBE_H_
#include <exception>
namespace {
// implementation enabled for non-reference types
template <class T>
struct maybe {
maybe() : valid(false) {} // default constructor
maybe(const T& val) : valid(true) { // contructor from wrapped value
new ((void*)storage) T(val);
}
maybe(const maybe &other) { // copy constructor
valid = other.valid;
if (valid) {
new ((void*)storage) T(other.get_ref());
}
}
maybe(maybe &&other) : maybe() { // move constructor
std::swap(valid, other.valid);
std::swap(storage, other.storage);
}
~maybe() { // destructor
if (valid) {
get_ref().~T();
}
}
// assignment operator, uses copy-and-swap trick
maybe& operator =(maybe other) {
swap(*this, other);
return *this;
}
// type-coercion operator to get back to wrapped value
// calling without checking validity causes bad_exception
operator T&() {
if (!valid) {
throw std::bad_exception();
}
return get_ref();
}
// for checking validity of container
explicit operator bool() { return valid; }
private:
bool valid;
alignas(T) char storage[sizeof(T)];
T& get_ref() const { return *static_cast<T*>((void*)storage); }
};
// implementation enabled for reference types
template <class T>
struct maybe<T&> {
maybe() : valid(false) value(nullptr) {}
maybe(T& val) : valid(true), value(&val) {}
maybe(const maybe &other) : valid(other.valid), value(other.value) {}
operator T&() {
if (!valid) {
throw std::bad_exception();
}
return *value;
}
explicit operator bool() { return valid; }
private:
bool valid;
T* value;
};
} // namespace {
#endif//MAYBE_H_发布于 2014-11-03 00:14:35
如果您有一个引用的构造:
maybe(const T& val) : valid(true) {
new ((void*)storage) T(val);
}为什么不通过移动来构造:
maybe(T&& val) : valid(true) {
new ((void*)storage) T(std::forward<T>(val));
}当您交换存储时,您正在交换数组的char。
maybe(maybe &&other) : maybe() { // move constructor
std::swap(valid, other.valid);
std::swap(storage, other.storage);
}但是,如果类型T(存储在存储中)不能在字节级别上交换怎么办?非常有可能(这就是为什么我们有复制/移动构造函数)。所以当你在这里做交换的时候,你应该使用T的交换。
maybe(maybe &&other) : maybe() {
std::swap(valid, other.valid);
using std::swap;
swap(get_ref(), other.get_ref());
}您有一个副本赋值操作符:
// assignment operator, uses copy-and-swap trick
maybe& operator =(maybe other) {
swap(*this, other);
return *this;
}不如写一个移动赋值操作符:
// assignment operator, uses copy-and-swap trick
maybe& operator=(maybe&& other) {
using std::swap;
swap(*this, other);
return *this;
}好的。我看你是想把引用和正常类型区别对待。
template <class T>
struct maybe<T&> {但我不明白你为什么要以不同的方式对待他们。
https://codereview.stackexchange.com/questions/68686
复制相似问题