//===----------------------------------------------------------------------===//
//
// 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
// template<class ...Args>
// constexpr T& __emplace(Args&& ...);
#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 = -1;
NonMovable() = default;
constexpr explicit NonMovable(int v) : value(v) { }
NonMovable(NonMovable&&) = delete;
NonMovable& operator=(NonMovable&&) = delete;
};
constexpr bool test() {
{
using T = std::tuple<>;
using Cache = std::ranges::__non_propagating_cache<T>;
Cache cache;
T& result = cache.__emplace();
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();
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(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();
assert(&result == &*cache);
assert(result == T());
}
{
using T = std::tuple<X<0>, X<1>>;
using Cache = std::ranges::__non_propagating_cache<T>;
Cache cache;
T& result = cache.__emplace(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();
assert(&result == &*cache);
assert(result.value == -1);
}
return true;
}
int main(int, char**) {
static_assert(test());
test();
return 0;
}