Skip to content

Commit 60a22de

Browse files
JMazurkiewiczAlexisPerry
authored andcommitted
[libc++] LWG3382: NTTP for pair and array (llvm#85811)
Mark LWG3382 as "Nothing To Do" and add tests.
1 parent d3746de commit 60a22de

File tree

4 files changed

+322
-0
lines changed

4 files changed

+322
-0
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
11+
// <array>
12+
13+
// LWG-3382 NTTP for pair and array:
14+
// Two values a1 and a2 of type array<T, N> are template-argument-equivalent if and only if each pair of corresponding
15+
// elements in a1 and a2 are template-argument-equivalent.
16+
17+
#include <array>
18+
19+
#include <type_traits>
20+
21+
namespace test_full_type {
22+
template <class T, std::size_t S, std::array<T, S> A>
23+
struct test : std::false_type {};
24+
25+
template <>
26+
struct test<int, 3, std::array<int, 3>{1, 2, 3}> : std::true_type {};
27+
28+
static_assert(!test<int*, 4, std::array<int*, 4>{}>::value);
29+
static_assert(!test<int*, 3, std::array<int*, 3>{}>::value);
30+
static_assert(!test<int, 3, std::array<int, 3>{}>::value);
31+
static_assert(!test<int, 3, std::array<int, 3>{1}>::value);
32+
static_assert(!test<int, 3, std::array<int, 3>{1, 2}>::value);
33+
static_assert(!test<long, 3, std::array<long, 3>{1, 2, 3}>::value);
34+
static_assert(!test<unsigned int, 3, std::array<unsigned int, 3>{1, 2, 3}>::value);
35+
static_assert(test<int, 3, std::array<int, 3>{1, 2, 3}>::value);
36+
} // namespace test_full_type
37+
38+
namespace test_ctad {
39+
template <std::array A>
40+
struct test : std::false_type {};
41+
42+
template <>
43+
struct test<std::array<int, 3>{4, 5, 6}> : std::true_type {};
44+
45+
static_assert(!test<std::array<int*, 4>{}>::value);
46+
static_assert(!test<std::array<int*, 3>{}>::value);
47+
static_assert(!test<std::array<int, 3>{}>::value);
48+
static_assert(!test<std::array<int, 3>{4}>::value);
49+
static_assert(!test<std::array<int, 3>{4, 5}>::value);
50+
static_assert(!test<std::array<long, 3>{4, 5, 6}>::value);
51+
static_assert(!test<std::array<unsigned int, 3>{4, 5, 6}>::value);
52+
static_assert(test<std::array<int, 3>{4, 5, 6}>::value);
53+
} // namespace test_ctad
54+
55+
namespace test_auto {
56+
template <auto A>
57+
struct test : std::false_type {};
58+
59+
template <>
60+
struct test<std::array<int, 3>{7, 8, 9}> : std::true_type {};
61+
62+
static_assert(!test<std::array<int*, 4>{}>::value);
63+
static_assert(!test<std::array<int*, 3>{}>::value);
64+
static_assert(!test<std::array<int, 3>{}>::value);
65+
static_assert(!test<std::array<int, 3>{7}>::value);
66+
static_assert(!test<std::array<int, 3>{7, 8}>::value);
67+
static_assert(!test<std::array<long, 3>{7, 8, 9}>::value);
68+
static_assert(!test<std::array<unsigned int, 3>{7, 8, 9}>::value);
69+
static_assert(test<std::array<int, 3>{7, 8, 9}>::value);
70+
} // namespace test_auto
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
11+
// <array>
12+
13+
// LWG-3382 NTTP for pair and array:
14+
// array<T, N> is a structural type ([temp.param]) if T is a structural type.
15+
16+
#include <array>
17+
18+
#include <cstddef>
19+
#include <string>
20+
21+
struct LiteralBase {};
22+
struct LiteralNSDM {};
23+
24+
struct LiteralType : LiteralBase {
25+
LiteralNSDM nsdm;
26+
};
27+
28+
struct NotALiteral {
29+
NotALiteral() {}
30+
};
31+
32+
int i;
33+
NotALiteral not_a_literal;
34+
35+
namespace test_full_type {
36+
template <class T, std::size_t S, std::array<T, S> A>
37+
struct test {};
38+
39+
using A = test<int, 2, std::array{2, 3}>;
40+
using B = test<LiteralType, 0, std::array<LiteralType, 0>{}>;
41+
using C = test<int*, 1, std::array<int*, 1>{&i}>;
42+
using D = test<NotALiteral*, 1, std::array<NotALiteral*, 1>{&not_a_literal}>;
43+
44+
using E = test<NotALiteral, 1, std::array<NotALiteral, 1>{}>;
45+
// expected-error-re@*:* {{non-type template parameter has non-literal type 'std::array<NotALiteral, 1U{{L{0,2}.*}}>'}}
46+
47+
using F = test<std::string, 2, std::array<std::string, 2>{}>;
48+
// expected-error-re@*:* {{type 'std::array<{{(std::)?}}string, 2U{{L{0,2}.*}}>' {{(\(aka 'array<basic_string<char>, 2UL{0,2}>'\) )?}}of non-type template parameter is not a structural type}}
49+
} // namespace test_full_type
50+
51+
namespace test_ctad {
52+
template <std::array A>
53+
struct test {};
54+
55+
using A = test<std::array{2, 3}>;
56+
using B = test<std::array<LiteralType, 0>{}>;
57+
using C = test<std::array<int*, 1>{&i}>;
58+
using D = test<std::array<NotALiteral*, 1>{&not_a_literal}>;
59+
60+
using E = test<std::array<NotALiteral, 1>{}>;
61+
// expected-error@-1 {{non-type template parameter has non-literal type 'std::array<NotALiteral, 1>'}}
62+
63+
using F = test<std::array<std::string, 2>{}>;
64+
// expected-error@-1 {{type 'std::array<string, 2>' (aka 'std::array<std::string, 2>') of non-type template parameter is not a structural type}}
65+
} // namespace test_ctad
66+
67+
namespace test_auto {
68+
template <auto A>
69+
struct test {};
70+
71+
using A = test<std::array{2, 3}>;
72+
using B = test<std::array<LiteralType, 0>{}>;
73+
using C = test<std::array<int*, 1>{&i}>;
74+
using D = test<std::array<NotALiteral*, 1>{&not_a_literal}>;
75+
76+
using E = test<std::array<NotALiteral, 1>{}>;
77+
// expected-error@-1 {{non-type template parameter has non-literal type 'std::array<NotALiteral, 1>'}}
78+
79+
using F = test<std::array<std::string, 2>{}>;
80+
// expected-error@-1 {{type 'std::array<std::string, 2>' (aka 'array<basic_string<char>, 2>') of non-type template parameter is not a structural type}}
81+
} // namespace test_auto
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
// UNSUPPORTED: clang-17
11+
12+
// <utility>
13+
14+
// LWG-3382 NTTP for pair and array:
15+
// Two values p1 and p2 of type pair<T, U> are template-argument-equivalent ([temp.type]) if and only if
16+
// p1.first and p2.first are template-argument-equivalent and p1.second and p2.second are template-argument-equivalent.
17+
18+
#include <utility>
19+
20+
#include <type_traits>
21+
22+
int i = 0;
23+
int j = 1;
24+
25+
namespace test_full_type {
26+
template <class T, class U, std::pair<T, U> P>
27+
struct test : std::false_type {};
28+
29+
template <>
30+
struct test<int&, int, std::pair<int&, int>{i, 5}> : std::true_type {};
31+
32+
static_assert(!test<int*, int*, std::pair<int*, int*>{}>::value);
33+
static_assert(!test<int*, int, std::pair<int*, int>{}>::value);
34+
static_assert(!test<int&, int*, std::pair<int&, int*>{i, nullptr}>::value);
35+
static_assert(!test<int&, int, std::pair<int&, int>{j, 0}>::value);
36+
static_assert(!test<int&, int, std::pair<int&, int>{j, 5}>::value);
37+
static_assert(!test<int&, int, std::pair<int&, int>{i, 0}>::value);
38+
static_assert(!test<int&, unsigned int, std::pair<int&, unsigned int>{j, 0}>::value);
39+
static_assert(test<int&, int, std::pair<int&, int>{i, 5}>::value);
40+
} // namespace test_full_type
41+
42+
namespace test_ctad {
43+
template <std::pair P>
44+
struct test : std::false_type {};
45+
46+
template <>
47+
struct test<std::pair<int&, int>{i, 10}> : std::true_type {};
48+
49+
static_assert(!test<std::pair<int*, int*>{}>::value);
50+
static_assert(!test<std::pair<int*, int>{}>::value);
51+
static_assert(!test<std::pair<int&, int*>{i, nullptr}>::value);
52+
static_assert(!test<std::pair<int&, int>{j, 0}>::value);
53+
static_assert(!test<std::pair<int&, int>{j, 10}>::value);
54+
static_assert(!test<std::pair<int&, int>{i, 0}>::value);
55+
static_assert(!test<std::pair<int&, unsigned int>{j, 0}>::value);
56+
static_assert(test<std::pair<int&, int>{i, 10}>::value);
57+
} // namespace test_ctad
58+
59+
namespace test_auto {
60+
template <auto P>
61+
struct test : std::false_type {};
62+
63+
template <>
64+
struct test<std::pair<int&, int>{i, 15}> : std::true_type {};
65+
66+
static_assert(!test<std::pair<int*, int*>{}>::value);
67+
static_assert(!test<std::pair<int*, int>{}>::value);
68+
static_assert(!test<std::pair<int&, int*>{i, nullptr}>::value);
69+
static_assert(!test<std::pair<int&, int>{j, 0}>::value);
70+
static_assert(!test<std::pair<int&, int>{j, 15}>::value);
71+
static_assert(!test<std::pair<int&, int>{i, 0}>::value);
72+
static_assert(!test<std::pair<int&, unsigned int>{j, 0}>::value);
73+
static_assert(test<std::pair<int&, int>{i, 15}>::value);
74+
} // namespace test_auto
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
// UNSUPPORTED: clang-17
11+
12+
// <utility>
13+
14+
// LWG-3382 NTTP for pair and array:
15+
// pair<T, U> is a structural type ([temp.param]) if T and U are both structural types.
16+
17+
#include <utility>
18+
19+
#include <functional>
20+
#include <string>
21+
22+
struct LiteralBase {};
23+
struct LiteralNSDM {};
24+
25+
struct LiteralType : LiteralBase {
26+
LiteralNSDM nsdm;
27+
};
28+
29+
struct NotALiteral {
30+
NotALiteral() {}
31+
};
32+
33+
int i;
34+
NotALiteral not_a_literal;
35+
36+
namespace test_full_type {
37+
template <class T, class U, std::pair<T, U> P>
38+
struct test {};
39+
40+
using A = test<int, int, std::pair{0, 1}>;
41+
using B = test<int&, int&, std::make_pair(std::ref(i), std::ref(i))>;
42+
using C = test<const int&, const int&, std::make_pair(std::cref(i), std::cref(i))>;
43+
using D = test<LiteralType, LiteralType, std::pair<LiteralType, LiteralType>{}>;
44+
using E = test<int*, int*, std::pair<int*, int*>{&i, &i}>;
45+
using F = test<NotALiteral&, NotALiteral&, std::make_pair(std::ref(not_a_literal), std::ref(not_a_literal))>;
46+
47+
using G = test<int&&, int&&, std::pair<int&&, int&&>{std::move(i), std::move(i)}>;
48+
// expected-error@*:* {{type 'std::pair<int &&, int &&>' of non-type template parameter is not a structural type}}
49+
50+
using H = test<NotALiteral, NotALiteral, std::pair<NotALiteral, NotALiteral>{}>;
51+
// expected-error@*:* {{non-type template parameter has non-literal type 'std::pair<NotALiteral, NotALiteral>'}}
52+
53+
using I = test<std::string, std::string, std::pair<std::string, std::string>{}>;
54+
// expected-error-re@*:* {{type 'std::pair<{{(std::)?}}string, {{(std::)?}}string>' {{(\(aka 'pair<basic_string<char>, basic_string<char>>'\) )?}}of non-type template parameter is not a structural type}}
55+
} // namespace test_full_type
56+
57+
namespace test_ctad {
58+
template <std::pair P>
59+
struct test {};
60+
61+
using A = test<std::pair{2, 3}>;
62+
using B = test<std::make_pair(std::ref(i), std::ref(i))>;
63+
using C = test<std::make_pair(std::cref(i), std::cref(i))>;
64+
using D = test<std::pair<LiteralType, LiteralType>{}>;
65+
using E = test<std::pair<int*, int*>{&i, &i}>;
66+
using F = test<std::make_pair(std::ref(not_a_literal), std::ref(not_a_literal))>;
67+
68+
using G = test<std::pair<int&&, int&&>{std::move(i), std::move(i)}>;
69+
// expected-error@-1 {{type 'std::pair<int &&, int &&>' of non-type template parameter is not a structural type}}
70+
71+
using H = test<std::pair<NotALiteral, NotALiteral>{}>;
72+
// expected-error@-1 {{non-type template parameter has non-literal type 'std::pair<NotALiteral, NotALiteral>'}}
73+
74+
using I = test<std::pair<std::string, std::string>{}>;
75+
// expected-error@-1 {{type 'std::pair<string, string>' (aka 'std::pair<std::string, std::string>') of non-type template parameter is not a structural type}}
76+
} // namespace test_ctad
77+
78+
namespace test_auto {
79+
template <auto P>
80+
struct test {};
81+
82+
using A = test<std::pair{4, 5}>;
83+
using B = test<std::make_pair(std::ref(i), std::ref(i))>;
84+
using C = test<std::make_pair(std::cref(i), std::cref(i))>;
85+
using D = test<std::pair<LiteralType, LiteralType>{}>;
86+
using E = test<std::pair<int*, int*>{&i, &i}>;
87+
using F = test<std::make_pair(std::ref(not_a_literal), std::ref(not_a_literal))>;
88+
89+
using G = test<std::pair<int&&, int&&>{std::move(i), std::move(i)}>;
90+
// expected-error@-1 {{type 'std::pair<int &&, int &&>' of non-type template parameter is not a structural type}}
91+
92+
using H = test<std::pair<NotALiteral, NotALiteral>{}>;
93+
// expected-error@-1 {{non-type template parameter has non-literal type 'std::pair<NotALiteral, NotALiteral>'}}
94+
95+
using I = test<std::pair<std::string, std::string>{}>;
96+
// expected-error@-1 {{type 'std::pair<std::string, std::string>' (aka 'pair<basic_string<char>, basic_string<char>>') of non-type template parameter is not a structural type}}
97+
} // namespace test_auto

0 commit comments

Comments
 (0)