1
0
forked from boostorg/core

Implement empty_value

This commit is contained in:
Glen Fernandes
2018-08-22 11:09:31 -04:00
parent e1f070b7b4
commit f504872d89
4 changed files with 252 additions and 0 deletions

View File

@ -0,0 +1,113 @@
/*
Copyright 2018 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_CORE_EMPTY_VALUE_HPP
#define BOOST_CORE_EMPTY_VALUE_HPP
#include <boost/config.hpp>
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#include <utility>
#endif
#if defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION >= 40700)
#define BOOST_DETAIL_EMPTY_VALUE_BASE
#elif defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1800)
#define BOOST_DETAIL_EMPTY_VALUE_BASE
#elif defined(BOOST_MSVC) && (BOOST_MSVC >= 1800)
#define BOOST_DETAIL_EMPTY_VALUE_BASE
#elif defined(BOOST_CLANG) && !defined(__CUDACC__)
#if __has_feature(is_empty) && __has_feature(is_final)
#define BOOST_DETAIL_EMPTY_VALUE_BASE
#endif
#endif
namespace boost {
template<class T>
struct use_empty_value_base {
enum {
#if defined(BOOST_DETAIL_EMPTY_VALUE_BASE)
value = __is_empty(T) && !__is_final(T)
#else
value = false
#endif
};
};
struct empty_init_t { };
template<class T, unsigned = 0, bool = use_empty_value_base<T>::value>
class empty_value {
public:
empty_value()
: value_() { }
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class... Args>
empty_value(empty_init_t, Args&&... args)
: value_(std::forward<Args>(args)...) { }
#else
template<class U>
empty_value(empty_init_t, U&& value)
: value_(std::forward<U>(value)) { }
#endif
#else
template<class U>
empty_value(empty_init_t, const U& value)
: value_(value) { }
#endif
const T& get() const BOOST_NOEXCEPT {
return value_;
}
T& get() BOOST_NOEXCEPT {
return value_;
}
private:
T value_;
};
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
template<class T, unsigned N>
class empty_value<T, N, true>
: T {
public:
empty_value()
: T() { }
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class... Args>
empty_value(empty_init_t, Args&&... args)
: T(std::forward<Args>(args)...) { }
#else
template<class U>
empty_value(empty_init_t, U&& value)
: T(std::forward<U>(value)) { }
#endif
#else
template<class U>
empty_value(empty_init_t, const U& value)
: T(value) { }
#endif
const T& get() const BOOST_NOEXCEPT {
return *this;
}
T& get() BOOST_NOEXCEPT {
return *this;
}
};
#endif
} /* boost */
#endif

View File

@ -123,5 +123,8 @@ run to_address_test.cpp ;
run exchange_test.cpp ;
run exchange_move_test.cpp ;
run empty_value_test.cpp ;
run empty_value_size_test.cpp ;
use-project /boost/core/swap : ./swap ;
build-project ./swap ;

View File

@ -0,0 +1,60 @@
/*
Copyright 2018 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
#include <boost/core/empty_value.hpp>
#include <boost/core/lightweight_test.hpp>
struct T1 { };
struct S1
: boost::empty_value<T1, 0, true> { };
struct T2 {
int value;
};
struct S2
: boost::empty_value<T1, 0, true>
, boost::empty_value<T2, 1, true> { };
struct S3
: boost::empty_value<T1, 0, false>
, boost::empty_value<T2, 1, true> { };
struct T3 { };
struct S4
: boost::empty_value<T1, 0, true>
, boost::empty_value<T3, 1, true> { };
struct S5
: boost::empty_value<T1, 0, false>
, boost::empty_value<T3, 1, false> { };
struct S6
: boost::empty_value<T1, 0, true>
, boost::empty_value<T2, 1, true>
, boost::empty_value<T3, 2, true> { };
int main()
{
BOOST_TEST(sizeof(S1) == sizeof(T1));
BOOST_TEST(sizeof(S2) == sizeof(T2));
BOOST_TEST(sizeof(S3) > sizeof(T2));
BOOST_TEST(sizeof(S4) == sizeof(T1));
BOOST_TEST(sizeof(S5) > sizeof(T1));
BOOST_TEST(sizeof(S6) == sizeof(T2));
return boost::report_errors();
}
#else
int main()
{
return 0;
}
#endif

76
test/empty_value_test.cpp Normal file
View File

@ -0,0 +1,76 @@
/*
Copyright 2018 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/core/empty_value.hpp>
#include <boost/core/lightweight_test.hpp>
struct empty {
operator bool() const {
return false;
}
operator bool() {
return true;
}
};
class type {
public:
type()
: value_(false) { }
explicit type(bool value)
: value_(value) { }
operator bool() const {
return value_;
}
private:
bool value_;
};
void test_bool()
{
const boost::empty_value<bool> v1(boost::empty_init_t(), true);
BOOST_TEST(v1.get());
boost::empty_value<bool> v2;
BOOST_TEST(!v2.get());
v2 = v1;
BOOST_TEST(v2.get());
v2.get() = false;
BOOST_TEST(!v2.get());
}
void test_empty()
{
empty e;
const boost::empty_value<empty> v1(boost::empty_init_t(), e);
BOOST_TEST(!v1.get());
boost::empty_value<empty> v2;
BOOST_TEST(v2.get());
v2 = v1;
BOOST_TEST(v2.get());
v2.get() = empty();
BOOST_TEST(v2.get());
}
void test_type()
{
const boost::empty_value<type> v1(boost::empty_init_t(), true);
BOOST_TEST(v1.get());
boost::empty_value<type> v2;
BOOST_TEST(!v2.get());
v2 = v1;
BOOST_TEST(v2.get());
v2.get() = type();
BOOST_TEST(!v2.get());
}
int main()
{
test_bool();
test_empty();
test_type();
return boost::report_errors();
}