Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ tests\GH_005546_containers_size_type_cast
tests\GH_005553_regex_character_translation
tests\GH_005768_pow_accuracy
tests\GH_005800_stable_sort_large_alignment
tests\GH_005968_headers_provide_begin_end
tests\LWG2381_num_get_floating_point
tests\LWG2510_tag_classes
tests\LWG2597_complex_branch_cut
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

import os

from stl.test.format import STLTestFormat, TestStep
from stl.test.tests import TestType


class CustomTestFormat(STLTestFormat):
def getBuildSteps(self, test, litConfig, shared):
exeSourceDir = os.path.dirname(test.getSourcePath())
_, outputBase = test.getTempPaths()

sourceFiles = []
for filename in os.listdir(exeSourceDir):
if filename.endswith('.cpp'):
sourceFiles.append(os.path.join(exeSourceDir, filename))

if TestType.COMPILE in test.testType:
cmd = [test.cxx, '/c', *sourceFiles, *test.flags, *test.compileFlags]
elif TestType.RUN in test.testType:
shared.execFile = outputBase + '.exe'
cmd = [test.cxx, *sourceFiles, *test.flags, *test.compileFlags, '/Fe' + shared.execFile,
'/link', *test.linkFlags]

yield TestStep(cmd, shared.execDir, shared.env, False)
4 changes: 4 additions & 0 deletions tests/std/tests/GH_005968_headers_provide_begin_end/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_matrix.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

import os
import site
site.addsitedir(os.path.dirname(os.path.dirname(__file__)))
import GH_005968_headers_provide_begin_end.custom_format

config.test_format = GH_005968_headers_provide_begin_end.custom_format.CustomTestFormat()
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

// Intentionally avoid including anything, relevant headers are included in .cpp files.
// Test requirements of N5014 [iterator.range]/1
// LWG-3987 added headers <flat_meow>

namespace detail {

// file test_iterator.cpp uses a non-std container and thus we can't rely on ADL to find begin/end etc.
using namespace std;

// Define minimal metaprogramming tools, avoid including anything

#define DEFINE_CONDITIONAL_CALLER_OF(member_name) \
template <typename T, typename = void> \
struct conditional_caller_of_##member_name { \
constexpr void operator()(T& t) { \
(void) t; \
} \
}; \
\
template <typename T> \
struct conditional_caller_of_##member_name<T&, decltype((void) static_cast<T*>(nullptr)->member_name())> { \
constexpr auto operator()(T& t) { \
return member_name(t); \
} \
};

#define CONDITIONALLY_CALL(c, member_name) conditional_caller_of_##member_name<decltype(c)>{}(c)

DEFINE_CONDITIONAL_CALLER_OF(rbegin);
DEFINE_CONDITIONAL_CALLER_OF(rend);
DEFINE_CONDITIONAL_CALLER_OF(crbegin);
DEFINE_CONDITIONAL_CALLER_OF(crend);
DEFINE_CONDITIONAL_CALLER_OF(size);
DEFINE_CONDITIONAL_CALLER_OF(ssize);
DEFINE_CONDITIONAL_CALLER_OF(empty);
DEFINE_CONDITIONAL_CALLER_OF(data);


template <typename C>
void test_free_container_functions(C& c) {
(void) begin(c);
(void) end(c);
(void) cbegin(c);
(void) cend(c);
CONDITIONALLY_CALL(c, rbegin); // missing e.g. for forward_list
CONDITIONALLY_CALL(c, rend); // missing e.g. for forward_list
CONDITIONALLY_CALL(c, crbegin); // missing e.g. for forward_list
CONDITIONALLY_CALL(c, crend); // missing e.g. for forward_list
CONDITIONALLY_CALL(c, size); // missing e.g. for optional
CONDITIONALLY_CALL(c, ssize); // missing e.g. for optional
CONDITIONALLY_CALL(c, empty); // missing e.g. for valarray
CONDITIONALLY_CALL(c, data); // missing e.g. for valarray
}

inline void test_free_array_functions() {
int a[]{1, 2, 3};

(void) begin(a);
(void) end(a);
(void) cbegin(a);
(void) cend(a);
(void) rbegin(a);
(void) rend(a);
(void) crbegin(a);
(void) crend(a);
(void) size(a);
#if _HAS_CXX20
(void) ssize(a);
#endif
(void) empty(a);
(void) data(a);
}
} // namespace detail

template <typename C>
void shared_test(C& c) {
detail::test_free_container_functions(c);
// as_const from <utility> not required to be available
detail::test_free_container_functions(const_cast<C const&>(c));

detail::test_free_array_functions();
}
48 changes: 48 additions & 0 deletions tests/std/tests/GH_005968_headers_provide_begin_end/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

void test_array();
void test_deque();
void test_flat_map();
void test_flat_set();
void test_forward_list();
void test_hive();
void test_inplace_vector();
void test_iterator();
void test_list();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test_iterator() seems missing.

void test_map();
void test_optional();
void test_regex();
void test_set();
void test_span();
void test_stacktrace();
void test_string();
void test_string_view();
void test_unordered_map();
void test_unordered_set();
void test_valarray();
void test_vector();

int main() {
test_array();
test_deque();
test_flat_map();
test_flat_set();
test_forward_list();
test_hive();
test_inplace_vector();
test_iterator();
test_list();
test_map();
test_optional();
test_regex();
test_set();
test_span();
test_stacktrace();
test_string();
test_string_view();
test_unordered_map();
test_unordered_set();
test_valarray();
test_vector();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <array>

#include "shared_test.hpp"

void test_array() {
std::array<int, 3> container{1, 2, 3};
shared_test(container);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <deque>

#include "shared_test.hpp"

void test_deque() {
std::deque<int> container{1, 2, 3};
shared_test(container);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <version>
#if defined(__cpp_lib_flat_map)

#include <flat_map>

#include "shared_test.hpp"

void test_flat_map() {
{
std::flat_map<int, int> container{
{1, 5},
{3, 7},
};
shared_test(container);
}

{
std::flat_multimap<int, int> container2{
{1, 5},
{3, 7},
};
shared_test(container2);
}
}

#else // ^^^ defined(__cpp_lib_flat_map) / feature not available vvv

void test_flat_map() {}

#endif // feature not available
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <version>
#if defined(__cpp_lib_flat_set)

#include <flat_set>

#include "shared_test.hpp"

void test_flat_set() {
{
std::flat_set container{1, 2, 3};
shared_test(container);
}

{
std::flat_multiset container2{1, 2, 3};
shared_test(container2);
}
}

#else // ^^^ defined(__cpp_lib_flat_set) / feature not available vvv

void test_flat_set() {}

#endif // feature not available
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <forward_list>

#include "shared_test.hpp"

void test_forward_list() {
std::forward_list<int> container{1, 2, 3};
shared_test(container);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <version>
#if defined(__cpp_lib_hive)

#include <hive>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto, this file should be added when implementing hive.


#include "shared_test.hpp"

void test_hive() {
std::hive<int> container{1, 2, 3};
shared_test(container);
}

#else // ^^^ defined(__cpp_lib_hive) / feature not available vvv

void test_hive() {}

#endif // feature not available
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should drop this file at this moment. It should be added when implementing inplace_vector.

Copy link
Contributor Author

@vmichal vmichal Dec 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although I have created a soft link by mentioning the relevant issues, I think relying on authors of inplace_vector, hive or optional range accessors to update this test in the future is a completely redundant mental burden and waste of time.

I like the current solution since it tests the current WP's requirements completely and will continue to do so until a new container is added. I personally see no issue in testing "future technology" when it is properly guarded with feature test macros. I consider this in line with their intended use case. Especially in this case, where I don't speculatively test some unstable API.

// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <version>
#if defined(__cpp_lib_inplace_vector)

#include <inplace_vector>

#include "shared_test.hpp"

void test_inplace_vector() {
std::inplace_vector<int, 3> container{1, 2, 3};
shared_test(container);
}

#else // ^^^ defined(__cpp_lib_inplace_vector) / feature not available vvv

void test_inplace_vector() {}

#endif // feature not available
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <list>

#include "shared_test.hpp"

void test_list() {
std::list<int> container{1, 2, 3};
shared_test(container);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <iterator>

#include "shared_test.hpp"

struct minimal_container {
static constexpr size_t magic_value = 3376942;

constexpr void begin() const {}
constexpr void end() const {}
constexpr void cbegin() const {}
constexpr void cend() const {}
constexpr void crbegin() const {}
constexpr void crend() const {}
constexpr void rbegin() const {}
constexpr void rend() const {}
constexpr size_t size() const {
return magic_value;
}
constexpr void empty() const {}
constexpr void data() const {}
};


// Self-test the template machinery to check it properly detects member functions
namespace detail {
template <typename C>
constexpr bool minimal_container_test(C& c) {
// when the CONDITIONALLY_CALL expression fails to detect the member, it has type voi, i.e. clearly
// incompatible with operator==. If the detection mechanism did not work properly, this would fail to compile.
return CONDITIONALLY_CALL(c, size) == minimal_container::magic_value;
}

constexpr minimal_container min_cont;
static_assert(minimal_container_test(min_cont), "The member detection utility is broken");
} // namespace detail

void test_iterator() {
minimal_container container;

shared_test(container);
}
Loading