Please use GitHub pull requests for new patches. Avoid migrating existing patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
libcxx/test/libcxx/ranges/range.nonprop.cache/emplace.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 ...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; } | |||||
}; | |||||
Quuxplusone: `friend constexpr` https://quuxplusone.github.io/blog/2021/04/03/static-constexpr-whittling… | |||||
Done.
I just want to use any type where I can pass heterogeneous arguments through to the constructor.
It's not valid to do that, though, cause there is no way to perform move elision in that case AFAICT. ldionne: > friend constexpr https://quuxplusone.github.io/blog/2021/04/03/static-constexpr-whittling… | |||||
std::ranges::__non_propagating_cache<NonMovable> cache; NonMovable& result = cache.__emplace(); assert(&result == &*cache); Quuxplusone: > In this PR, though, it seems more important to test that it's legal to `__emplace` a… | |||||
Ah, I see what you meant now. Done. ldionne: Ah, I see what you meant now. Done. | |||||
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})); | |||||
} | |||||
return true; | |||||
} | |||||
int main(int, char**) { | |||||
static_assert(test()); | |||||
test(); | |||||
return 0; | |||||
} |
friend constexpr https://quuxplusone.github.io/blog/2021/04/03/static-constexpr-whittling-knife/
and consider line-breaking somewhere.
High-level comment: I'm not sure what benefit you get from the templated operator== or the use of tuple. If you just want something with a couple of weird constructors, why not string?
In this PR, though, it seems more important to test that it's legal to __emplace a NonMovable, similar to what you did below in the __emplace_deref test.