首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类似于boost的实现::可为函数故障建模

类似于boost的实现::可为函数故障建模
EN

Code Review用户
提问于 2014-11-02 21:52:43
回答 1查看 1.2K关注 0票数 6

其思想是您可以有一个名为maybe的简单类型,它包装了另一个类型,它提供了不可能从函数返回值的能力。我肯定它还不完美,但它有我正在寻找的广泛的打击。我主要是在找我漏掉的案子,还有其他我忽略的东西。

代码语言:javascript
复制
#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_
EN

回答 1

Code Review用户

发布于 2014-11-03 00:14:35

如果您有一个引用的构造:

代码语言:javascript
复制
    maybe(const T& val) : valid(true)  {
        new ((void*)storage) T(val);
    }

为什么不通过移动来构造:

代码语言:javascript
复制
    maybe(T&& val) : valid(true)  {
        new ((void*)storage) T(std::forward<T>(val));
    }

当您交换存储时,您正在交换数组的char。

代码语言:javascript
复制
    maybe(maybe &&other) : maybe() {            // move constructor
        std::swap(valid,   other.valid);
        std::swap(storage, other.storage);
    }

但是,如果类型T(存储在存储中)不能在字节级别上交换怎么办?非常有可能(这就是为什么我们有复制/移动构造函数)。所以当你在这里做交换的时候,你应该使用T的交换。

代码语言:javascript
复制
    maybe(maybe &&other) : maybe() {
        std::swap(valid,   other.valid);

        using std::swap;
        swap(get_ref(),    other.get_ref());
    }

您有一个副本赋值操作符:

代码语言:javascript
复制
    // assignment operator, uses copy-and-swap trick
    maybe& operator =(maybe other) {
        swap(*this, other);
        return *this;
    }

不如写一个移动赋值操作符:

代码语言:javascript
复制
    // assignment operator, uses copy-and-swap trick
    maybe& operator=(maybe&& other) {

        using std::swap;
        swap(*this, other);

        return *this;
    }

好的。我看你是想把引用和正常类型区别对待。

代码语言:javascript
复制
template <class T>        
struct maybe<T&> {

但我不明白你为什么要以不同的方式对待他们。

票数 5
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/68686

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档