eranpeer / FakeIt

C++ mocking made easy. A simple yet very expressive, headers only library for c++ mocking.
MIT License
1.22k stars 170 forks source link

Fixes and workarounds for older gcc compilers #277

Closed kingsley-cheung closed 2 years ago

kingsley-cheung commented 2 years ago

I saw compilation issues when using FakeIt with a legacy project that needs gcc 4.8.5.

A problem with an ambiguous call to std::abs(double): g++ -flto -D__GXX_EXPERIMENTAL_CXX0X__ -I"../include" -I"../config/standalone" -O0 -g3 -Wall -Wextra -Wno-ignored-qualifiers -c -fmessage-length=0 -std=c++11 -MMD -MP -MF"argument_matching_tests.d" -MT"argument_matching_tests.d" -o "argument_matching_tests.o" "../tests/argument_matching_tests.cpp" In file included from ../include/fakeit/invocation_matchers.hpp:21:0, from ../include/fakeit/RecordedMethodBody.hpp:18, from ../include/fakeit/StubbingImpl.hpp:15, from ../include/fakeit/MockImpl.hpp:17, from ../include/fakeit/Mock.hpp:11, from ../include/fakeit/fakeit_root.hpp:3, from ../config/standalone/fakeit.hpp:4, from ../tests/argument_matching_tests.cpp:11: ../include/fakeit/argument_matchers.hpp: In instantiation of ‘bool fakeit::internal::ApproxEqCreator<ExpectedTRef, ExpectedMarginTRef>::createMatcher() const::Matcher::matches(const ActualT&) const [with ActualT = double; ExpectedTRef = int&&; ExpectedMarginTRef = double&&]’: ../include/fakeit/argument_matchers.hpp:476:17: required from ‘fakeit::TypedMatcher<ActualT>* fakeit::internal::ApproxEqCreator<ExpectedTRef, ExpectedMarginTRef>::createMatcher() const [with ActualT = double; ExpectedTRef = int&&; ExpectedMarginTRef = double&&]’ ../include/fakeit/MatchersCollector.hpp:57:104: required from ‘typename std::enable_if<typename fakeit::naked_type<A>::type::IsTypeCompatible<typename fakeit::naked_type<typename std::tuple_element<index, std::tuple<_Elements ...> >::type>::type>::value, void>::type fakeit::MatchersCollector<index, arglist>::CollectMatchers(Head&&) [with Head = fakeit::internal::ApproxEqCreator<int&&, double&&>; unsigned int index = 0u; arglist = {double}; typename std::enable_if<typename fakeit::naked_type<A>::type::IsTypeCompatible<typename fakeit::naked_type<typename std::tuple_element<index, std::tuple<_Elements ...> >::type>::type>::value, void>::type = void]’ ../include/fakeit/MethodMockingContext.hpp:260:13: required from ‘typename std::enable_if<(sizeof (matcherCreators ...) == sizeof (arglist ...)), void>::type fakeit::MethodMockingContext<R, arglist>::setMatchingCriteria(matcherCreators&& ...) [with matcherCreators = {fakeit::internal::ApproxEqCreator<int&&, double&&>}; R = int; arglist = {double}; typename std::enable_if<(sizeof (matcherCreators ...) == sizeof (arglist ...)), void>::type = void]’ ../include/fakeit/MethodMockingContext.hpp:302:112: required from ‘fakeit::MockingContext<R, arglist>& fakeit::MockingContext<R, arglist>::Using(arg_matcher&& ...) [with arg_matcher = {fakeit::internal::ApproxEqCreator<int&&, double&&>}; R = int; arglist = {double}]’ ../tests/argument_matching_tests.cpp:301:3: required from here ../include/fakeit/argument_matchers.hpp:474:65: error: call of overloaded ‘abs(double)’ is ambiguous return std::abs(actual - this->_expected) <= this->_expectedMargin;

There was also a problem with list-initialization used in constructor member initializer lists: g++ -flto -D__GXX_EXPERIMENTAL_CXX0X__ -I"../include" -I"../config/standalone" -O0 -g3 -Wall -Wextra -Wno-ignored-qualifiers -c -fmessage-length=0 -std=c++11 -MMD -MP -MF"stubbing_tests.d" -MT"stubbing_tests.d" -o "stubbing_tests.o" "../tests/stubbing_tests.cpp" In file included from ../include/fakeit/StubbingImpl.hpp:16:0, from ../include/fakeit/MockImpl.hpp:17, from ../include/fakeit/Mock.hpp:11, from ../include/fakeit/fakeit_root.hpp:3, from ../config/standalone/fakeit.hpp:4, from ../tests/stubbing_tests.cpp:13: ../include/fakeit/StubbingProgress.hpp: In instantiation of ‘fakeit::helper::ArgValue<T, N>::ArgValue(T&&) [with T = std::vector<std::basic_string<char> >&; int N = 2]’: ../include/fakeit/StubbingProgress.hpp:493:49: required from ‘fakeit::helper::ArgValue<ArgType, std::is_placeholder<_Tp>::value> fakeit::placeholders::operator<=(PlaceHolder, ArgType&&) [with PlaceHolder = std::_Placeholder<2>; ArgType = std::vector<std::basic_string<char> >&; typename std::enable_if<static_cast<bool>(std::is_placeholder<_Tp>::value), bool>::type <anonymous> = 1u]’ ../tests/stubbing_tests.cpp:203:65: required from here ../include/fakeit/StubbingProgress.hpp:365:57: error: invalid initialization of non-const reference of type ‘std::vector<std::basic_string<char> >&’ from an rvalue of type ‘<brace-enclosed initializer list>’ ArgValue(T &&v): value { std::forward<T>(v) } {} ^ ../include/fakeit/StubbingProgress.hpp: In instantiation of ‘fakeit::helper::ArgValue<T, N>::ArgValue(T&&) [with T = std::vector<std::basic_string<char> >&; int N = 1]’: ../include/fakeit/StubbingProgress.hpp:493:49: required from ‘fakeit::helper::ArgValue<ArgType, std::is_placeholder<_Tp>::value> fakeit::placeholders::operator<=(PlaceHolder, ArgType&&) [with PlaceHolder = std::_Placeholder<1>; ArgType = std::vector<std::basic_string<char> >&; typename std::enable_if<static_cast<bool>(std::is_placeholder<_Tp>::value), bool>::type <anonymous> = 1u]’ ../tests/stubbing_tests.cpp:213:65: required from here ../include/fakeit/StubbingProgress.hpp:365:57: error: invalid initialization of non-const reference of type ‘std::vector<std::basic_string<char> >&’ from an rvalue of type ‘<brace-enclosed initializer list>’ make: *** [stubbing_tests.o] Error 1

Unit tests pass with GCC 4.8.5 and 7.5.0 with these minor changes.

kingsley-cheung commented 2 years ago

I have also added a check to see if __has_include is defined as suggested in by gnu documentation. Again this is another problem with older compilers.

From what I understand __has_include is a C++17 feature so we need to support older compilers without it since FakeIt is targeted at C++11.

coveralls commented 2 years ago

Coverage Status

Coverage remained the same at 99.925% when pulling f7de08277f14f321e3eab1fd744032cc0185889a on kingsley-cheung:fixes-for-older-gcc-compilers into ded6e4700be5cec17fd15c9de78267f53c52a0a7 on eranpeer:master.

FranckRJ commented 2 years ago

Thanks for the fixes, but just so you know, the compatibility with older compiler (non C++11-compliant compilers) is done as a best effort and won't really by checked by the CI, so in future updates some changes can make FakeIt incompatible again.

kingsley-cheung commented 2 years ago

Thanks for the fixes, but just so you know, the compatibility with older compiler (non C++11-compliant compilers) is done as a best effort and won't really by checked by the CI, so in future updates some changes can make FakeIt incompatible again.

@FranckRJ No problems. Understood regarding the best effort approach, so I will bear that in mind going forward. And thanks for your work on making Fakeit available.