Compare ptr with nullptr in gtest - c++

Have some code:
EXPECT_NE(nullptr,ptr);
And I get the following compilation error:
'operator <<' is ambiguous
could be 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<<void>(std::nullptr_t)'
or 'std::basic_ostream<char,std::char_traits<char>> &testing::internal2::operator <<<char,std::char_traits<char>,T>(std::basic_ostream<char,std::char_traits<char>> &,const T &)'
Could this be a library version problem?

If you want to be more explicit, you could also use
EXPECT_TRUE(ptr != nullptr);
(that's what I normally do)
Btw. funnily enough, in my work project I still have to work with C++98 (still building for Sun and AIX, although it will soon go away) and I ended up creating my own NullPtrT class and NullPtr object in the common library, which actually works with gtest EXPECT_EQ and EXPECT_NE macros. So that I can do
EXPECT_NE(NullPtr, ptr);
I don't remember how exactly I made that work :)

I've run into the same problem recently with GTest 1.8.0, but only when using Visual Studio 2019 in C++17 mode. Visual Studio 2019 works fine in C++14 mode, and neither Clang nor GCC seem to have the same problem in C++17 mode.
The issue is that with C++17 there's a new overload in the standard library for the std::ostream::operator<< that takes a nullptr_t, but GTest also provides its own, so your compiler does not know which one to use.
If you have full control over your version of GTest then https://github.com/google/googletest/pull/1620/commits/f66ab00704cd47e4e63ef6d425ca14b9192aaebb is a change for GTest-1.8.0 that resolves the issue: It's not as easy as deleting the overload, because the function in question is a template whose other instantiations are still used. Instead, the solution is to define an explicit void PrintTo(std::nullptr_t, ::std::ostream* os) function that will then automatically be used, no longer deferring to the ambiguous overloads.
When modifying GTest is not an option then the solutions mentioned in the other answers to not use EXPECT_EQ/EXPECT_NE when one parameter is a nullptr_t are your best bet.

namespace {
template<class T>
auto not_nullptr(T*p) -> testing::AssertionResult
{
if (p)
return testing::AssertionSuccess();
else
return testing::AssertionFailure() << "pointer is null";
}
}
...
EXPECT_TRUE(not_nullptr(ptr));
reference:
https://github.com/google/googletest/blob/master/docs/advanced.md#using-a-function-that-returns-an-assertionresult

Google Test documentation says that,
When comparing a pointer to NULL, use EXPECT_EQ(ptr, nullptr)
instead of EXPECT_EQ(ptr, NULL)
When comparing a pointer to NULL, use EXPECT_NE(ptr, nullptr)
instead of EXPECT_NE(ptr, NULL).
Therefore, you can just use EXPECT_NE(ptr, nullptr);.
Read more: https://google.github.io/googletest/reference/assertions.html#EXPECT_NE

#include "gtest.h"
using ::testing::NotNull;
ASSERT_THAT(ptr, NotNull());
This will give you some more descriptive errors and keeps you using the existing framework. Other benefits are compatibility with smart pointers and raw pointers.
Other matchers can be found on the gtest matchers documentation.

Related

What SFINAE tricks can I safely use on all MSVC >= 2013?

In Qt I had the brilliant (cough, cough) idea to start defining overloads of qHash (the hashing function used for QHash, one of Qt's associative containers) for Standard Library datatypes: std::basic_string, std::shared_ptr and the like.
There could be a shortcut for this process: instead of chasing "any Standard Library type that could be used as a key in QHash" and adding a qHash overload for it, I could just define qHash automatically if the type has a std::hash specialization for it (reasonably assuming that we don't want to do more than what the Standard Library does in this process).
That is, I could implement something like this using expression SFINAE:
template<typename T>
auto qHash(const T &t) -> decltype(std::hash<T>()(t))
{
return std::hash<T>()(t);
}
Unfortunately, although Qt demands a C++11 compiler, expression SFINAE is not allowed anywhere because MSVC does not fully support it (at the time of this writing: all MSVC versions, up to and including VS15 preview 5. Anyhow, Qt must support all the way back to 2013).
Hence, the question: is there a way to do the same, in a way that
does not use expression SFINAE
is guaranteed to work on all MSVC versions >= 2013?
I was thinking a plain good ol' C++98 SFINAE construction via enable_if and the like, but other SO answers (like this one) make me think that MSVC 2013 may miscompile that too, so the result becomes unacceptable again.
I do not think you need expression SFINAE for this, something along these lines should work.
template<typename T>
typename std::hash<T>::result_type qHash(const T &t)
{
return std::hash<T>()(t);
}
Or pretty much any approach that does SFINAE on hash::result_type. Unfortunately for you, hash::result_type is deprecated in C++17, but you can still #ifdef this code for MSVC 2013.

Compiler error when passing unique_ptr<Derived> to function that accepts unique_ptr<Base> parameter

I have the following code:
class A {
};
class B : public A {
};
class C {
void func(std::unique_ptr<A> &&p) {
}
void init() {
std::unique_ptr<B> b(new B);
func(std::move(b));
}
};
According to this, the above code should work fine. Apparently, unique_ptr was designed to be able to mimic the polymorphism of built-in pointers. Compiler errors don't appear on VS2015, but do appear in Android Studio.
The IntelliJ error reads: "Parameter type mismatch: Class 'std::unique_ptr is not compatible with class 'std::unique_ptr'"
When I try to build, the compiler error reads: "error: no viable conversion from 'unique_ptr' to 'unique_ptr'".
The following flag is set in my Cmake file (building a native library in Android Studio):
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
Android Studio is using GNU 4.9.
I should note that the up-casting works fine when done at initialization (i.e. std::unique_ptr a(new B);), but for some reason it doesn't work when trying to pass as a parameter (as seems acceptable based on the above-listed link).
I know I can probably work around this, but I don't want to sacrifice the clarity and safety of my code because the compiler is being hinky. Up until now, the majority of STL has worked fine in Android Studio, but I may just have to build the library independently in VS if I want to use this functionality.
Edit: In case it's unclear, my question specifically is: Why am I getting this error in one IDE, but not in the other? Is there some way for me to make it work in the former (so I can continue to code in that environment)?
Edit 2: When I try to do the exact same thing with shared_ptr(for both passed derived and expected base parameters), no error displays. Weird.

Compiling boost with MSVC2015 with /std:c++latest (or C++17/N4190)

When I try to build boost with MSVC2015 with the /std:c++latest flag I get an error:
boost\algorithm\string\detail\case_conv.hpp(33): error C2143: syntax error: missing ',' before '<'
Which points to:
// a tolower functor
template<typename CharT>
struct to_lowerF : public std::unary_function<CharT, CharT>
Now this seems to be due to N4190 as mentioned here: https://www.visualstudio.com/en-us/news/releasenotes/vs2015-update3-vs
/std:c++latest also controls the removal of the following old
features: N4190 "Removing auto_ptr, random_shuffle(), And Old Stuff",
P0004R1 "Removing Deprecated Iostreams Aliases", LWG 2385
"function::assign allocator argument doesn't make sense", and various
non-Standard features (the std::tr1 namespace, some TR1-only
machinery, and the std::identity struct).
When using:
std::string a,b;
return boost::iequals(a,b);
And using boost::ilexicographical_compare.
Its also mentioned here:
https://blogs.msdn.microsoft.com/vcblog/2015/06/19/c111417-features-in-vs-2015-rtm/
Stephan T. Lavavej - MSFT
Azarien: Removing auto_ptr/etc. will have positive consequences. It will prevent new code from using outdated/complicated/unsafe
machinery, and it will reduce confusion among non-expert users. (For
example, unnecessary unary_function/binary_function inheritance is
common, because many users thought that STL algorithms/containers
required this, when in fact only the outdated adapters did.) And
auto_ptr in particular is unsafe, because its mutating "copy"
constructor silently moves from lvalues.
So how do I get boost to compile with VC2015's /std:c++latest? Right now it appears boost isn't C++17 compatible?
Define the macro _HAS_AUTO_PTR_ETC before including any headers. For your own code, if you're using Visual Studio's build system, this is best accomplished by way of your project's Preprocessor Definitions setting. For building Boost itself, add define=_HAS_AUTO_PTR_ETC to your b2/bjam invocation.
Other previously-standard functionality implicitly disabled by /std:c++latest can be controlled by defining the macros _HAS_FUNCTION_ASSIGN, _HAS_OLD_IOSTREAMS_MEMBERS, and _HAS_TR1_NAMESPACE. These macros are all outlined in the following blog articles:
STL Fixes In VS 2015 Update 3
VS 2015 Update 2’s STL is C++17-so-far Feature Complete

Why doesn't Qt's qHash() have an overload for std::shared_ptr?

I just found out, to my surprise, that the following code does not compile out of the box in C++14 using Qt 5.4:
QSet<std::shared_ptr<SomeType>> var;
The problem is that there is no overload of the qHash() method for std::shared_ptr, or any other smart pointer as far as I can see:
http://doc.qt.io/qt-5/qhash.html#related-non-members
It seems natural to me to have the following overload (or something similar):
template <typename T>
uint qHash(const std::shared_ptr<T>& ptr, uint seed = 0)
{
return qHash(ptr.get(), seed);
}
but it does not exist. This cannot simply be something the Qt developers overlooked. Do I need to include a special header? What is the reason why this does not exist?
Speak of the devil, and he doth appear:
https://codereview.qt-project.org/113340
This cannot simply be something the Qt developers overlooked.
It's not an overlook, it's just that Qt doesn't have endless resources to add qHash overloads to any STL type which has an operator==.
This cannot simply be something the Qt developers overlooked.
It is, and it's not something that was overlooked - it simply is impossible to write all the code at once. One has to stop somewhere and do a release. Feel free to submit a code revision that will fix this :) Make sure, though, that the revision will build on all platforms, and with all supported compilers - some of them have libraries without std::shared_ptr!

I can't use if ( ifs == NULL) command in VS 2013

When compiling this code:
std::ifstream ifs("somefile.txt");
if(ifs == NULL)
I get an error
no operator matches these operands "=="
I got the same error in every project with VS 2013, but I didn't have any problem in VS 2010.
How to solve this?
The definition of std::basic_ios (from which std::basic_ifstream inherits) changed in C++11. In particular, it's conversion operator operator void* changed to explicit operator bool, so what you're trying to do is no longer valid. Nonetheless, it was never a common way to check the state of your stream. Instead, just do if (!ifs).
The C++ standard changes, now faster than ever, and MSVC has a habit of just mixing together the different standards until they fully support the latest one. You can expect some code to break when things change, although the committee aim to minimise this as much as possible.