首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用删除的复制器模拟方法返回对象?

如何用删除的复制器模拟方法返回对象?
EN

Stack Overflow用户
提问于 2017-02-28 09:39:53
回答 2查看 9.5K关注 0票数 12

如果一个接口有一个函数来创建一个带有已删除复制器的对象,那么如何模拟这个函数呢?Gmock似乎在内部使用对象的复制构造函数。

例如。

代码语言:javascript
复制
// The object with deleted copy-ctor and copy-assignment
class TTest
{
public:
    TTest() = delete;
    TTest(const TTest&) = delete;
    TTest& operator=(const TTest&) = delete;
    TTest(TTest&&) = default;
    TTest& operator=(TTest&&) = default;

    explicit TTest(int) {
    }
};

// My interface to mock
class MyInterface
{
    public:
        virtual ~MyInterface() {}
        virtual TTest GetUniqueTest() = 0;
};

// The mock
class MockMyInterface: public MyInterface{
    public:
        MOCK_METHOD0(GetUniqueTest, TTest());
}

编译错误显示:

代码语言:javascript
复制
gmock/gmock-spec-builders.h:1330:20: error: use of deleted function 'TTest::TTest(const TTest&)'
     T retval(value_);
...
gmock/gmock-actions.h:190:52: error: use of deleted function 'TTest::TTest(const TTest&)'
         internal::BuiltInDefaultValue<T>::Get() : *value_;
...
gmock/internal/gmock-internal-utils.h:371:71: error: use of deleted function 'TTest::TTest(const TTest&)'
       *static_cast<volatile typename remove_reference<T>::type*>(NULL));

如果方法返回std::unique_ptr<T>,由于std::unique_ptr<T>也删除了复制-ctor,所以错误是相同的。

因此,我的问题是:如何模拟那些使用已删除的复制函数返回对象的方法?

我使用的是googletest v1.7、GCC 5.3.0和Ubuntu14.04.1。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-02-28 10:24:23

正如我的的评论中所提到的,GoogleTest1.8似乎支持模拟这些函数(文档)。

至于1.7,我找到了一个解决方案这里

首先,创建一个实用程序类来包装不可复制的对象:

代码语言:javascript
复制
template <typename T>
class Mover
{
public:
    Mover(T&& object)
      : object(std::move(object)),
        valid(true)
    {
    }

    Mover(const Mover<T>& other)
      : object(const_cast<T&&>(other.object)),
        valid(true)
    {
        assert(other.valid);
        other.valid = false;
    }

    Mover& operator=(const Mover& other)
    {
        assert(other.valid);
        object = const_cast<T&&>(other.object);
        other.valid = false;
        valid = true;
    }

    T& get()
    {
        assert(valid);
        return object;
    }

    const T& get() const
    {
        assert(valid);
        return *object;
    }

private:
    T object;
    mutable bool valid;
};

template <typename T>
inline Mover<T> Movable(T&& object)
{
    return Mover<T>(std::move(object));
}

然后创建一个代理模拟:

代码语言:javascript
复制
class MockMyInterface : public MyInterface
{
public:
    MOCK_METHOD0(GetUniqueTest_, Mover<TTest>());
    TTest GetUniqueTest()
    {
        return std::move(GetUniqueTest_().get());
    }
}
票数 4
EN

Stack Overflow用户

发布于 2017-03-01 09:40:14

在这里回答我自己的问题,只是为了提供最新的信息。

使用googletest 发行版1.8.0或更高版本,它引入了ByMove(...)并支持本地只返回移动类型。

所以代码编译OK:

代码语言:javascript
复制
class MockMyInterface: public MyInterface{
    public:
        MOCK_METHOD0(GetUniqueTest, TTest());
}

但是在运行时,它会引发异常,因为gmock不知道如何返回默认的TTest

代码语言:javascript
复制
C++ exception with description "Uninteresting mock function call - returning default value.
    Function call: GetUniqueTest()
    The mock function has no default action set, and its return type has no default value set." thrown in the test body.

通过在模拟类中设置默认操作,可以轻松地解决这一问题:

代码语言:javascript
复制
ON_CALL(*this, GetUniqueTest()).WillByDefault(Return(ByMove(TTest(0))));

注意事项:对于std::unique_ptr<T>,因为它有默认构造函数,因此默认情况下返回nullptr unique_ptr

因此,如果使用googletest 1.8.0或更高版本,将所有内容组合在一起,我们可以这样做:

代码语言:javascript
复制
// My interface to mock
class MyInterface
{
    public:
        virtual ~MyInterface() {}
        virtual TTest GetUniqueTest() = 0;
        virtual std::unique_ptr<int> GetUniqueInt() = 0;
};

// The mock
class MockMyInterface: public MyInterface{
    public:
        MOCK_METHOD0(GetUniqueTest, TTest());
        MOCK_METHOD0(GetUniqueInt, std::unique_ptr<int>());
        MockMyInterface() {
            ON_CALL(*this, GetUniqueTest())
                .WillByDefault(Return(ByMove(TTest(0))));
        }
};

参考资料:模拟使用仅移动类型的方法。

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

https://stackoverflow.com/questions/42505119

复制
相关文章

相似问题

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