C ++ - 使用decltype或auto

时间:2017-08-09 07:13:39

标签: c++

我有一个对象“a”,我想把它复制到一个对象“b”中但是稍微修改它而不修改“a”。那就是这样的:

class SomeClass{

public:
    int a;

public:
    SomeClass(int _a)       {a = _a;}
    SomeClass& doStuff()    {++a; return *this;}

};

const SomeClass a( 25);
const auto b = SomeClass( a).doStuff();

这很好用但是我现在/我不想写“a”的类型,然后我想出了这个解决方案:

const auto b = std::remove_const<decltype( a)>::type( a).doStuff();

我这样做了吗?对此有一个不那么难看的解决方案吗? (我不必两次输入“a”。)使用汽车或其他东西。最好不要宏。

3 个答案:

答案 0 :(得分:5)

怎么样

template<typename T>
T copy(const T& t) { return T(t); }

const auto b = copy(a).doStuff();

答案 1 :(得分:1)

阐述VTT的评论:

class SomeClass;
class DoStuff
{
    friend class SomeClass;
    SomeClass const& c;
public:
    explicit DoStuff(SomeClass const& c)
        : c(c)
    { }
};

class SomeClass
{
    int a;
public:
    SomeClass(int a)
        : a(a)
    { }

    SomeClass(SomeClass const& other)
        : a(other.a)
    { }

    SomeClass(DoStuff d)
        : SomeClass(d.c)
    {
        doStuff();
    }
};

SomeClass const a(7);
SomeClass const b((DoStuff(a)));

唯一不幸的缺点:我们需要额外的括号来防止b被解释为函数SomeClass const b (DoStuff a) { }a作为参数名...

我个人更倾向于将DoStuff作为SomeClass的内部类,但这会迫使你再次重复类名:

SomeClass const b (( SomeClass::DoStuff(d) ));

(哈哈,现在我得到了自己 - 一个重复一个类名,即使没有内部类,我仍然有...)

好的,在有人呻吟之前:

SomeClass const b { DoStuff(a) };

最近提到过?好吧,猜测,我个人绝对不会欣赏这种语法并尽可能避免使用它 - 即使使用初始化列表,我仍然会在括号内放置括号:std::vector<int> v({7, 10, 12}); - 但这是一个不同的主题...

答案 2 :(得分:1)

更好的方法是为专用于SomeClass操作的doStuff引用创建一个可分辨的包装器类型,并使构造函数接受此类型。此方法消除了创建临时SomeClass对象以及将额外参数传递到构造函数的可能开销。虽然SomeClass相当简单,但没有多大区别。

class
t_DoingStuffSomeClassWrap final
{
    #pragma region Fields

    private: SomeClass const & m_inst;

    #pragma endregion

    private:
    t_DoingStuffSomeClassWrap(void) = delete;

    public:
    t_DoingStuffSomeClassWrap(t_DoingStuffSomeClassWrap const & that) noexcept
    :   m_inst{that.m_inst}
    {}      

    public: explicit
    t_DoingStuffSomeClassWrap(SomeClass const & inst) noexcept
    :   m_inst{inst}
    {}

    private: t_DoingStuffSomeClassWrap &
    operator =(t_DoingStuffSomeClassWrap const & that) = delete;

    private: t_DoingStuffSomeClassWrap &
    operator =(t_DoingStuffSomeClassWrap && that) = delete;

    public: SomeClass const &
    Unwrap(void) const noexcept
    {
        return(m_inst);
    }
};

// inside of SomeClass definition:
public: explicit
SomeClass(t_DoingStuffSomeClassWrap const wrap)
:   a{wrap.Unwrap().a}
{
    doStuff();
}

//  actual use
const SomeClass b{t_DoingStuffSomeClassWrap{a}};