2

让我们使用 gmock 1.8 来编写这段代码:

#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include <variant>

class Obj {
  public:
    MOCK_METHOD0( mock, void() );//<-!!!
};

using Variant = std::variant<Obj>;

TEST(Test, Test) {
  Obj obj;
  Variant variant = obj;
}

尝试使用 clang++ 编译时,会出现以下编译错误:

error: no viable conversion from 'Obj' to 'Variant' (aka 'variant<Obj>')
  Variant variant = obj;
          ^         ~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/variant:1081:7: note: candidate constructor not viable: no known conversion from 'Obj' to 'const std::variant<Obj> &' for 1st argument
      variant(const variant& __rhs) = default;
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/variant:1093:2: note: candidate template ignored: substitution failure [with _Tp = Obj &, $1 = void, $2 = void]: implicit instantiation of undefined template 'std::variant<Obj>::__to_type_impl<18446744073709551615, false>'
        variant(_Tp&& __t)
        ^

(g ++的错误只说

error: conversion from ‘Obj’ to non-scalar type ‘Variant’ {aka ‘std::variant<Obj>’} requested
   Variant variant = obj;
                     ^~~

)

当 MOCK_METHOD0 宏的行被注释掉时,代码编译正常。我确信在这种情况下调用的是复制构造函数(第 1081 行中的那个)。

这是为什么?如果我迁移到 gmock 1.10,问题会消失吗?还是不可能使用 gmock 模拟的变体?感谢您提供有关如何自己找到它的任何解释或提示。

4

1 回答 1

2

如果您展开MOCK_METHOD0宏,您将看到它在您的类定义中插入了以下数据成员:

class Obj
{
public:
    // ...
    mutable ::testing::FunctionMocker<void()> gmock0_mock_12;
};

由于您不提供自己的复制构造函数,因此编译器将隐式生成一个。它的默认实现将尝试执行逐个成员的复制。但是,检查 的定义FunctionMocker,可以看到以下通知:

// There is no generally useful and implementable semantics of
// copying a mock object, so copying a mock is usually a user error.
// Thus we disallow copying function mockers.  If the user really
// wants to copy a mock object, they should implement their own copy
// operation, for example:
//
//   class MockFoo : public Foo {
//    public:
//     // Defines a copy constructor explicitly.
//     MockFoo(const MockFoo& src) {}
//     ...
//   };
FunctionMocker(const FunctionMocker&) = delete;
FunctionMocker& operator=(const FunctionMocker&) = delete;

也就是说,FunctionMocker对象是不可复制的,模拟对象也是如此(它们隐式生成的复制构造函数也被删除)。

这是合理的。模拟的副本是否应该具有相同的期望?它应该仔细检查对破坏的期望吗?

如果您想将模拟放在一个变体中,您可以就地构建它,或者:

std::variant<Obj> variant(std::in_place_type_t<Obj>{});

或者:

std::variant<Obj> variant;
variant.emplace<Obj>();
于 2019-11-24T11:55:16.487 回答