简体   繁体   English

*** 尚未声明(尽管已声明)

[英]*** has not been declared (though it is)

That is a part of a larger project, but looks like this files cause the problem.这是一个更大项目的一部分,但看起来这个文件会导致问题。

StreamImpl.hpp StreamImpl.hpp

class StreamImpl {
...
    template <typename Type>
    StreamImpl &operator<<(T &&out) noexcept;
...
};

#include "StreamTemplateImpl.cpp"

StreamTemplateImpl.cpp StreamTemplateImpl.cpp

// Templates implementation needed for test purposes
#include "StreamImpl.hpp"
#include "MockStreamImpl.hpp"

using ::utils::Dispatcher;
using ::mock::MockStreamImpl; // Error here

template <typename Type>
StreamImpl &operator<<(T &&out) noexcept
{
    return Dispatcher<MockStreamImpl>::Instance().Get()->OutOperator(out);
}

MockStreamImpl.hpp MockStreamImpl.hpp

#include "StreamImpl.hpp"
namespace mock {
using ::StreamImpl;
class MockStreamImpl {
   MOCK_METHOD(...); // Gmock methods
};
}  // namespace mock

Helper class to avoid code duplication:帮助程序 class 以避免代码重复:

Fixture.hpp Fixture.hpp

#include "MockStreamImpl.hpp"

namespace fixture {
using ::mock::MockStreamImpl;
using ::utils::Dispatcher;
using ::testing::Test;

class UtStream : public Test {
   // Class for setting up mocks and common test data which is used as fixture in tests
   
    StreamImpl kDefaultStream_{};
}
}  // namespace fixture

And file with test cases, which uses StreamImpl mocks:并带有测试用例的文件,它使用 StreamImpl 模拟:

Tests.cpp测试.cpp

#include "Fixture.hpp"
... // Test cases

CMakeLists.txt CMakeLists.txt

add_unit_test(
    TEST_NAME
        test_unit
    TEST_SOURCES
        unit_test_source_file.cpp
        ${SOURCES}/file_to_test.cpp
        ${MOCKS}/fake_stream_impl.cpp // source file with fake StreamImpl functions  implementations which redirects to mocks
    INCLUDE_DIRS
        ${INCLUDES}
        ${MOCKS}
        ${UTILS}
        ${FAKE_STREAM_IMPL_TEMPLATES} 
    LIBS
        gmock
        gtest
        gtest_main
)

And when I try to compile this I got当我尝试编译这个时,我得到了

In file included from /path/src/StreamImpl.hpp:281:0,
                 from /path/test/unit/mocks/MockStreamImpl.hpp:23,
                 from /path/test/unit/mocks/Fixture.hpp:24,
                 from /path/test/unit/unit_test_source_file.cpp:23:                                                                                                       
    /path/test/unit/mocks/fake_templates/StreamTemplateImpl.cpp:25:18: error: '::mock' has not been declared                                                     
     using ::mock::MockStreamImpl;

All headers have guards so I'm not sure about circular dependency, but if it is, I'll be really thankful for explanation.所有标题都有保护,所以我不确定循环依赖,但如果是的话,我会非常感谢你的解释。

Also when I compile this without Fixture.hpp ( Fixture.hpp content is merged into unit_test_source_file.cpp ) all builds perfectly.此外,当我在没有Fixture.hpp的情况下编译它( Fixture.hpp内容合并到unit_test_source_file.cpp )时,所有构建都完美。

I'm really can't understand where is the problem and will be thankful for any help.我真的不明白问题出在哪里,并感谢您的帮助。

I saw a lot of related topics but neither seems contains answer for me.我看到了很多相关的话题,但似乎都没有为我提供答案。

You have an architectural problem, you are abstracting the different types of streams in a bad spot, that cannot easily be untangled.你有一个架构问题,你在一个不好的地方抽象了不同类型的流,这不容易被解开。 The mock interface is too tightly entwined with the code under test.模拟接口与被测代码过于紧密地交织在一起。 You can hack around this, but you are better off stopping and thinking through exactly what you want to test.你可以解决这个问题,但你最好停下来仔细思考你想要测试的内容。

Sort of side note:旁注排序:

StreamImpl is a bad idea. StreamImpl是个坏主意。

StreamImpl& operator<<(T &&out) noexcept;

is non-standard and part of how you got into this problem.是非标准的,并且是您遇到此问题的一部分。 If you use the standard如果你使用标准

std::ostream & operator<<(std::ostream & strm,  T &&out) noexcept;

and turn StreamImpl into a child of std::ostream you can pass in a re-write of MockStreamImpl that is ALSO a child of std::ostream and completely hide the specialization of the stream inside the stream rather than the function writing to the stream. and turn StreamImpl into a child of std::ostream you can pass in a re-write of MockStreamImpl that is ALSO a child of std::ostream and completely hide the specialization of the stream inside the stream rather than the function writing to the stream .

Side note to the side note: Templating operator<< isn't a very good idea either.旁注的旁注:模板化operator<<也不是一个好主意。 Most types don't have similar-enough rules to be printable by a generic function.大多数类型没有足够相似的规则,无法由通用 function 打印。 This leads to goofy output or confused error messages when the << template tries to invoke itself because it's still the best match.<<模板尝试调用自身时,这会导致愚蠢的 output 或混淆错误消息,因为它仍然是最佳匹配。

What went wrong:什么地方出了错:

If we follow the includes and perform the substitutions we can see what the compiler sees:如果我们遵循包含并执行替换,我们可以看到编译器看到的内容:

#include "MockStreamImpl.hpp"

namespace fixture {
using ::mock::MockStreamImpl;
using ::utils::Dispatcher;
using ::testing::Test;

class UtStream : public Test {
   // Class for setting up mocks and common test data which is used as fixture in tests
   
    StreamImpl kDefaultStream_{};
}
}  // namespace fixture

leads to导致

#include "StreamImpl.hpp"
namespace mock {
using ::StreamImpl;
class MockStreamImpl {
   MOCK_METHOD(...); // Gmock methods
};
}  // namespace mock
namespace fixture {
using ::mock::MockStreamImpl;
using ::utils::Dispatcher;
using ::testing::Test;

class UtStream : public Test {
   // Class for setting up mocks and common test data which is used as fixture in tests
   
    StreamImpl kDefaultStream_{};
}
}  // namespace fixture

and then to然后到

class StreamImpl {
...
    template <typename Type>
    StreamImpl &operator<<(T &&out) noexcept;
...
};

#include "StreamTemplateImpl.cpp"

namespace mock {
using ::StreamImpl;
class MockStreamImpl {
   MOCK_METHOD(...); // Gmock methods
};
}  // namespace mock
namespace fixture {
using ::mock::MockStreamImpl;
using ::utils::Dispatcher;
using ::testing::Test;

class UtStream : public Test {
   // Class for setting up mocks and common test data which is used as fixture in tests
   
    StreamImpl kDefaultStream_{};
}
}  // namespace fixture

and then, yawn, to然后,打哈欠,到

class StreamImpl {
...
    template <typename Type>
    StreamImpl &operator<<(T &&out) noexcept;
...
};

// Templates implementation needed for test purposes
#include "StreamImpl.hpp"
#include "MockStreamImpl.hpp"

using ::utils::Dispatcher;
using ::mock::MockStreamImpl; // Error here

template <typename Type>
StreamImpl &operator<<(T &&out) noexcept
{
    return Dispatcher<MockStreamImpl>::Instance().Get()->OutOperator(out);
}
namespace mock {
using ::StreamImpl;
class MockStreamImpl {
   MOCK_METHOD(...); // Gmock methods
};
}  // namespace mock
namespace fixture {
using ::mock::MockStreamImpl;
using ::utils::Dispatcher;
using ::testing::Test;

class UtStream : public Test {
   // Class for setting up mocks and common test data which is used as fixture in tests
   
    StreamImpl kDefaultStream_{};
}
}  // namespace fixture

and since StreamImpl.hpp and MockStreamImpl.hpp are protected by include guards we get并且由于 StreamImpl.hpp 和 MockStreamImpl.hpp 受到包含守卫的保护,我们得到

class StreamImpl {
...
    template <typename Type>
    StreamImpl &operator<<(T &&out) noexcept;
...
};

// Templates implementation needed for test purposes

using ::utils::Dispatcher;
using ::mock::MockStreamImpl; // Error here

template <typename Type>
StreamImpl &operator<<(T &&out) noexcept
{
    return Dispatcher<MockStreamImpl>::Instance().Get()->OutOperator(out);
}
namespace mock { //because mock isn't found by the compiler until here
using ::StreamImpl;
class MockStreamImpl {
   MOCK_METHOD(...); // Gmock methods
};
}  // namespace mock
namespace fixture {
using ::mock::MockStreamImpl;
using ::utils::Dispatcher;
using ::testing::Test;

class UtStream : public Test {
   // Class for setting up mocks and common test data which is used as fixture in tests
   
    StreamImpl kDefaultStream_{};
}
}  // namespace fixture

where we can see that MockStreamImpl is required before it is defined.我们可以看到MockStreamImpl在定义之前是必需的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM