EmptyMemberPair.h#

Fully qualified name: carb/EmptyMemberPair.h

File members: carb/EmptyMemberPair.h

// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: LicenseRef-NvidiaProprietary
//
// NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
// property and proprietary rights in and to this material, related
// documentation and any modifications thereto. Any use, reproduction,
// disclosure or distribution of this material and related documentation
// without an express license agreement from NVIDIA CORPORATION or
// its affiliates is strictly prohibited.

#pragma once

#include <type_traits>
#include <utility>

namespace carb
{

struct ValueInitFirst
{
    constexpr explicit ValueInitFirst() = default;
};

struct InitBoth
{
    constexpr explicit InitBoth() = default;
};

template <class First, class Second, bool = std::is_empty<First>::value && !std::is_final<First>::value>
class EmptyMemberPair : private First
{
public:
    using FirstType = First;
    using SecondType = Second;

    template <class... Args2>
    constexpr explicit EmptyMemberPair(ValueInitFirst, Args2&&... args)
        : First{}, second{ std::forward<Args2>(args)... }
    {
    }

    template <class Arg1, class... Args2>
    constexpr explicit EmptyMemberPair(InitBoth, Arg1&& arg1, Args2&&... args2)
        : First(std::forward<Arg1>(arg1)), second(std::forward<Args2>(args2)...)
    {
    }

    constexpr FirstType& first() noexcept
    {
        return *this;
    }

    constexpr const FirstType& first() const noexcept
    {
        return *this;
    }

    SecondType second;
};

template <class First, class Second>
class EmptyMemberPair<First, Second, false>
{
public:
    using FirstType = First;
    using SecondType = Second;

    template <class... Args2>
    constexpr explicit EmptyMemberPair(ValueInitFirst, Args2&&... args)
        : m_first(), second(std::forward<Args2>(args)...)
    {
    }

    template <class Arg1, class... Args2>
    constexpr explicit EmptyMemberPair(InitBoth, Arg1&& arg1, Args2&&... args2)
        : m_first(std::forward<Arg1>(arg1)), second(std::forward<Args2>(args2)...)
    {
    }

    constexpr FirstType& first() noexcept
    {
        return m_first;
    }
    constexpr const FirstType& first() const noexcept
    {
        return m_first;
    }

private:
    FirstType m_first;

public:
    SecondType second;
};

} // namespace carb