D4451: Fix copy/move issues casude by __tuple_leafs's converting constructor
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@213888 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -17,6 +17,40 @@
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
template <class ...>
|
||||
struct never {
|
||||
enum { value = 0 };
|
||||
};
|
||||
|
||||
struct NoValueCtor
|
||||
{
|
||||
NoValueCtor() : id(++count) {}
|
||||
NoValueCtor(NoValueCtor const & other) : id(other.id) { ++count; }
|
||||
|
||||
// The constexpr is required to make is_constructible instantiate this template.
|
||||
// The explicit is needed to test-around a similar bug with is_convertible.
|
||||
template <class T>
|
||||
constexpr explicit NoValueCtor(T)
|
||||
{ static_assert(never<T>::value, "This should not be instantiated"); }
|
||||
|
||||
static int count;
|
||||
int id;
|
||||
};
|
||||
|
||||
int NoValueCtor::count = 0;
|
||||
|
||||
|
||||
struct NoValueCtorEmpty
|
||||
{
|
||||
NoValueCtorEmpty() {}
|
||||
NoValueCtorEmpty(NoValueCtorEmpty const &) {}
|
||||
|
||||
template <class T>
|
||||
constexpr explicit NoValueCtorEmpty(T)
|
||||
{ static_assert(never<T>::value, "This should not be instantiated"); }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
@@ -56,6 +90,23 @@ int main()
|
||||
assert(std::get<1>(t) == nullptr);
|
||||
assert(std::get<2>(t) == "text");
|
||||
}
|
||||
// __tuple_leaf<T> uses is_constructible<T, U> to disable its explicit converting
|
||||
// constructor overload __tuple_leaf(U &&). Evaluating is_constructible can cause a compile error.
|
||||
// This overload is evaluated when __tuple_leafs copy or move ctor is called.
|
||||
// This checks that is_constructible is not evaluated when U == __tuple_leaf.
|
||||
{
|
||||
std::tuple<int, NoValueCtor, int, int> t(1, NoValueCtor(), 2, 3);
|
||||
assert(std::get<0>(t) == 1);
|
||||
assert(std::get<1>(t).id == 1);
|
||||
assert(std::get<2>(t) == 2);
|
||||
assert(std::get<3>(t) == 3);
|
||||
}
|
||||
{
|
||||
std::tuple<int, NoValueCtorEmpty, int, int> t(1, NoValueCtorEmpty(), 2, 3);
|
||||
assert(std::get<0>(t) == 1);
|
||||
assert(std::get<2>(t) == 2);
|
||||
assert(std::get<3>(t) == 3);
|
||||
}
|
||||
// extensions
|
||||
{
|
||||
std::tuple<int, char*, std::string> t(2);
|
||||
|
||||
@@ -18,6 +18,18 @@
|
||||
|
||||
#include "../MoveOnly.h"
|
||||
|
||||
struct ConstructsWithTupleLeaf
|
||||
{
|
||||
ConstructsWithTupleLeaf() {}
|
||||
|
||||
ConstructsWithTupleLeaf(ConstructsWithTupleLeaf const &) { assert(false); }
|
||||
ConstructsWithTupleLeaf(ConstructsWithTupleLeaf &&) {}
|
||||
|
||||
template <class T>
|
||||
ConstructsWithTupleLeaf(T t)
|
||||
{ assert(false); }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
@@ -46,4 +58,12 @@ int main()
|
||||
assert(std::get<1>(t) == 1);
|
||||
assert(std::get<2>(t) == 2);
|
||||
}
|
||||
// A bug in tuple caused __tuple_leaf to use its explicit converting constructor
|
||||
// as its move constructor. This tests that ConstructsWithTupleLeaf is not called
|
||||
// (w/ __tuple_leaf)
|
||||
{
|
||||
typedef std::tuple<ConstructsWithTupleLeaf> d_t;
|
||||
d_t d((ConstructsWithTupleLeaf()));
|
||||
d_t d2(static_cast<d_t &&>(d));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user