Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement C++26 std::ignore #2922

Merged
merged 10 commits into from
Nov 30, 2024
47 changes: 47 additions & 0 deletions libcudacxx/include/cuda/std/__tuple_dir/ignore.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES.
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCUDACXX___TUPLE_IGNORE_H
#define _LIBCUDACXX___TUPLE_IGNORE_H

#include <cuda/std/detail/__config>

#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
# pragma GCC system_header
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
# pragma clang system_header
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
# pragma system_header
#endif // no system header

_LIBCUDACXX_BEGIN_NAMESPACE_STD

struct __ignore_t
{
davebayer marked this conversation as resolved.
Show resolved Hide resolved
__ignore_t() = default;

template <class... _Ts>
_LIBCUDACXX_HIDE_FROM_ABI constexpr __ignore_t(const _Ts&...) noexcept
{}

ericniebler marked this conversation as resolved.
Show resolved Hide resolved
template <class _Tp>
_LIBCUDACXX_HIDE_FROM_ABI constexpr const __ignore_t& operator=(const _Tp&) const noexcept
{
return *this;
}
};

namespace
{
_CCCL_GLOBAL_CONSTANT __ignore_t ignore{};
} // namespace

_LIBCUDACXX_END_NAMESPACE_STD

#endif // _LIBCUDACXX___TUPLE_IGNORE_H
16 changes: 1 addition & 15 deletions libcudacxx/include/cuda/std/detail/libcxx/include/tuple
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ template <class... Types>
#include <cuda/std/__functional/unwrap_ref.h>
#include <cuda/std/__fwd/array.h>
#include <cuda/std/__memory/allocator_arg_t.h>
#include <cuda/std/__tuple_dir/ignore.h>
#include <cuda/std/__tuple_dir/make_tuple_types.h>
#include <cuda/std/__tuple_dir/sfinae_helpers.h>
#include <cuda/std/__tuple_dir/structured_bindings.h>
Expand Down Expand Up @@ -1116,21 +1117,6 @@ _LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX14 tuple<_Tp&...> tie(_Tp&... __t)
return tuple<_Tp&...>(__t...);
}

template <class _Up>
struct __ignore_t
{
template <class _Tp>
_LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX14 const __ignore_t& operator=(_Tp&&) const
{
return *this;
}
};

namespace
{
_CCCL_GLOBAL_CONSTANT __ignore_t<unsigned char> ignore{};
} // namespace

template <class... _Tp>
_LIBCUDACXX_HIDE_FROM_ABI _CCCL_CONSTEXPR_CXX14 tuple<typename __unwrap_ref_decay<_Tp>::type...> make_tuple(_Tp&&... __t)
{
Expand Down
3 changes: 3 additions & 0 deletions libcudacxx/include/cuda/std/utility
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@
#endif // !_LIBCUDACXX_HAS_NO_SPACESHIP_OPERATOR
#include <cuda/std/initializer_list>

// [tuple.creation]
#include <cuda/std/__tuple_dir/ignore.h>

// [tuple.helper]
#include <cuda/std/__tuple_dir/tuple_element.h>
#include <cuda/std/__tuple_dir/tuple_size.h>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,39 @@

// constexpr unspecified ignore;

// UNSUPPORTED: c++98, c++03

#include <cuda/std/cassert>
#include <cuda/std/tuple>

#include "test_macros.h"

static_assert(cuda::std::is_trivial<decltype(cuda::std::ignore)>::value, "");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the record, is_trivial is almost never what you want, and in fact the whole notion of trivial types in the standard is going away. typically what you really want is either is_trivially_copyable or is_trivially_constructible or both.

Copy link
Contributor Author

@davebayer davebayer Nov 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is taken from libc++. I tried to find out if it is actually required to be trivial by the standard but I didn't find anything said about it. libstdc++ does not even implement this check in their tests, but the implementated type is trivial.

The most important thing is that it is trivially default constructible. I would change the check to is_trivially_default_constructible if you agree.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to have the is_trivially_default_constructible and an is_empty check


#if TEST_STD_VER >= 2017
[[nodiscard]] __host__ __device__ constexpr int test_nodiscard()
{
return 8294;
}
#endif // TEST_STD_VER >= 2017

__host__ __device__ TEST_CONSTEXPR_CXX14 bool test()
{
{ // Test that std::ignore provides constexpr converting assignment.
{
auto& ignore_v = cuda::std::ignore;
unused(ignore_v);
}

{ // Test that cuda::std::ignore provides converting assignment.
auto& res = (cuda::std::ignore = 42);
static_assert(noexcept(res = (cuda::std::ignore = 42)), "");
assert(&res == &cuda::std::ignore);
}
{ // Test bit-field binding.
struct S
{
unsigned int bf : 3;
};
S s{3};
auto& res = (cuda::std::ignore = s.bf);
assert(&res == &cuda::std::ignore);
}
{ // Test that cuda::std::ignore provides constexpr copy/move constructors
Expand All @@ -35,16 +57,18 @@ __host__ __device__ TEST_CONSTEXPR_CXX14 bool test()
moved = cuda::std::move(copy);
unused(moved);
}

#if TEST_STD_VER >= 2017
{
cuda::std::ignore = test_nodiscard();
}
#endif // TEST_STD_VER >= 2017

return true;
}
static_assert(cuda::std::is_trivial<decltype(cuda::std::ignore)>::value, "");

int main(int, char**)
{
{
constexpr auto& ignore_v = cuda::std::ignore;
unused(ignore_v);
}
test();
#if TEST_STD_VER >= 2014
static_assert(test(), "");
Expand Down
Loading