Skip to content

<xstd/misc/type_traits/conditional_data_member.hpp>

xstd::conditional_data_member, xstd::conditional_data_member_t

template<bool Condition, class Type, class Tag>
using conditional_data_member = conditional<Condition, Type, empty_member_type<Tag>>;

template<bool Condition, class Type, class Tag>
using conditional_data_member_t = conditional_t<Condition, Type, empty_member_type<Tag>>;

A data member's type where a condition holds, and a tagged empty type where it does not: Type when Condition holds, and otherwise empty_member_type<Tag>.

Notes

Declared with XSTD_NO_UNIQUE_ADDRESS, a member of this type takes no storage where the condition fails.

Example

Adapted from the example of std::conditional on cppreference.com, at revision 152806, by cppreference.com contributors. This example is under CC-BY-SA 3.0 and the GFDL, as cppreference.com's content is; the rest of this page is under the Boost Software License.

#include <xstd/misc/type_traits/conditional_data_member.hpp> // conditional_data_member, empty_member_type
#include <iostream>                                          // cout
#include <string_view>                                       // string_view
#include <type_traits>                                       // is_same_v

// The tag of the empty member that stands in for an absent counter.
struct counter;

// The name of each type the example picks, the same on every compiler.
template<class T>
[[nodiscard]] constexpr auto name() -> std::string_view
{
        if constexpr (std::is_same_v<T, int>) {
                return "int";
        } else if constexpr (std::is_same_v<T, xstd::empty_member_type<counter>>) {
                return "xstd::empty_member_type<counter>";
        } else {
                return "another type";
        }
}

auto main() -> int
{
        using Type1 = xstd::conditional_data_member<true, int, counter>::type;
        using Type2 = xstd::conditional_data_member<false, int, counter>::type;
        using Type3 = xstd::conditional_data_member<sizeof(int) >= sizeof(double), int, counter>::type;

        std::cout << name<Type1>() << '\n';
        std::cout << name<Type2>() << '\n';
        std::cout << name<Type3>() << '\n';
}

Output:

int
xstd::empty_member_type<counter>
xstd::empty_member_type<counter>

See also

Entity Relation
empty_member_type the type it picks where the condition fails
XSTD_NO_UNIQUE_ADDRESS lets that member take no storage
std::conditional the standard trait it is built on