diff --git a/lib/base/string.cpp b/lib/base/string.cpp index bad3116a5..2806902ac 100644 --- a/lib/base/string.cpp +++ b/lib/base/string.cpp @@ -47,7 +47,7 @@ String::String(Value&& other) String& String::operator=(Value&& other) { if (other.IsString()) - m_Data = std::move(other.Get()); + *this = std::move(other.Get()); // Will atomically bind to the move assignment operator below. else *this = static_cast(other); diff --git a/lib/base/value.cpp b/lib/base/value.cpp index ebf3ba60b..1e357a92a 100644 --- a/lib/base/value.cpp +++ b/lib/base/value.cpp @@ -9,9 +9,13 @@ using namespace icinga; template class boost::variant; template const double& Value::Get() const; +template double& Value::Get(); template const bool& Value::Get() const; +template bool& Value::Get(); template const String& Value::Get() const; +template String& Value::Get(); template const Object::Ptr& Value::Get() const; +template Object::Ptr& Value::Get(); const Value icinga::Empty; diff --git a/lib/base/value.hpp b/lib/base/value.hpp index 6e64abb43..9533d710c 100644 --- a/lib/base/value.hpp +++ b/lib/base/value.hpp @@ -140,14 +140,24 @@ public: return boost::get(m_Value); } + template + T& Get() + { + return boost::get(m_Value); + } + private: boost::variant m_Value; }; extern template const double& Value::Get() const; +extern template double& Value::Get(); extern template const bool& Value::Get() const; +extern template bool& Value::Get(); extern template const String& Value::Get() const; +extern template String& Value::Get(); extern template const Object::Ptr& Value::Get() const; +extern template Object::Ptr& Value::Get(); extern const Value Empty; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6ceb48683..c4b1041dd 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -166,6 +166,7 @@ add_boost_test(base base_string/index base_string/find base_string/vector_move + base_string/move_string_out_of_Value_type base_timer/construct base_timer/interval base_timer/invoke diff --git a/test/base-string.cpp b/test/base-string.cpp index 5b28c5481..50c1f6af8 100644 --- a/test/base-string.cpp +++ b/test/base-string.cpp @@ -1,6 +1,7 @@ /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */ #include "base/string.hpp" +#include "base/value.hpp" #include #include @@ -126,4 +127,20 @@ BOOST_AUTO_TEST_CASE(vector_move) BOOST_CHECK_EQUAL(oldAddr, newAddr); } +// Test that the move constructor of icinga::String actually moves the underlying std::string out of a Value instance. +// The constructor overload is only available on non-Windows platforms though, so we need to skip the test on Windows. +BOOST_AUTO_TEST_CASE(move_string_out_of_Value_type) +{ +#ifndef _MSC_VER + Value value("Icinga 2"); + String other = value.Get(); // We didn't request a move, so this should just copy the string. + BOOST_CHECK_EQUAL("Icinga 2", value.Get()); + BOOST_CHECK_EQUAL("Icinga 2", other); + + String newStr = std::move(value); + BOOST_CHECK_EQUAL("", value.Get()); + BOOST_CHECK_EQUAL(newStr, "Icinga 2"); +#endif /* _MSC_VER */ +} + BOOST_AUTO_TEST_SUITE_END()