Please use GitHub pull requests for new patches. Avoid migrating existing patches. Phabricator shutdown timeline
Differential D107932 Diff 366656 libcxx/test/libcxx/ranges/range.nonprop.cache/emplace_from.pass.cpp
Changeset View
Changeset View
Standalone View
Standalone View
libcxx/test/libcxx/ranges/range.nonprop.cache/emplace_from.pass.cpp
- This file was added.
//===----------------------------------------------------------------------===// | |||||
// | |||||
// 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 | |||||
// | |||||
//===----------------------------------------------------------------------===// | |||||
// UNSUPPORTED: c++03, c++11, c++14, c++17 | |||||
// UNSUPPORTED: libcpp-no-concepts | |||||
// UNSUPPORTED: libcpp-has-no-incomplete-ranges | |||||
// template<class Fn> | |||||
// constexpr T& __emplace_from(Fn const&); | |||||
#include <ranges> | |||||
#include <cassert> | |||||
#include <tuple> | |||||
template<int I> | |||||
struct X { | |||||
int value = -1; | |||||
template<int J> | |||||
friend constexpr bool operator==(X const& a, X<J> const& b) { return I == J && a.value == b.value; } | |||||
}; | |||||
struct NonMovable { | |||||
int value; | |||||
constexpr explicit NonMovable(int v) : value(v) { } | |||||
NonMovable(NonMovable&&) = delete; | |||||
}; | |||||
constexpr bool test() { | |||||
{ | |||||
using T = std::tuple<>; | |||||
using Cache = std::ranges::__non_propagating_cache<T>; | |||||
Cache cache; | |||||
T& result = cache.__emplace_from([] { return T(); }); | |||||
assert(&result == &*cache); | |||||
assert(result == T()); | |||||
} | |||||
{ | |||||
using T = std::tuple<X<0>>; | |||||
using Cache = std::ranges::__non_propagating_cache<T>; | |||||
Cache cache; | |||||
T& result = cache.__emplace_from([] { return T(X<0>{0}); }); | |||||
assert(&result == &*cache); | |||||
assert(result == T(X<0>{0})); | |||||
} | |||||
{ | |||||
using T = std::tuple<X<0>, X<1>>; | |||||
using Cache = std::ranges::__non_propagating_cache<T>; | |||||
Cache cache; | |||||
T& result = cache.__emplace_from([] { return T(X<0>{0}, X<1>{1}); }); | |||||
assert(&result == &*cache); | |||||
assert(result == T(X<0>{0}, X<1>{1})); | |||||
} | |||||
// Make sure that we do not require the type to be movable when we emplace it. | |||||
// Move elision should be performed instead, see http://eel.is/c++draft/range.nonprop.cache#note-1. | |||||
{ | |||||
using Cache = std::ranges::__non_propagating_cache<NonMovable>; | |||||
Cache cache; | |||||
NonMovable& result = cache.__emplace_from([] { return NonMovable(3); }); | |||||
assert(&result == &*cache); | |||||
assert(result.value == 3); | |||||
} | |||||
return true; | |||||
} | |||||
int main(int, char**) { | |||||
static_assert(test()); | |||||
test(); | |||||
return 0; | |||||
} |