diff --git a/include/etl/array.h b/include/etl/array.h index 1662419b..1bb92cea 100644 --- a/include/etl/array.h +++ b/include/etl/array.h @@ -1056,7 +1056,13 @@ namespace etl template constexpr auto make_array(TValues&&... values) ETL_NOEXCEPT -> etl::array { - return {etl::forward(values)...}; + // Forward each argument as its own deduced type, then convert explicitly to T. + // Forwarding as T (the old behaviour) made the call ill-formed for any const-qualified + // lvalue of type T: forward requires a non-const T&, and a T&& cannot bind to a + // reference-related const lvalue. The explicit conversion also keeps narrowing + // initialisers (e.g. make_array(0, 1)) working, which plain forwarding into the + // braced initialiser list would reject. + return {static_cast(etl::forward(values))...}; } #endif diff --git a/include/etl/deque.h b/include/etl/deque.h index 4ac0ac92..a35eda34 100644 --- a/include/etl/deque.h +++ b/include/etl/deque.h @@ -2535,7 +2535,13 @@ namespace etl template constexpr auto make_deque(TValues&&... values) -> etl::deque { - return {etl::forward(values)...}; + // Forward each argument as its own deduced type, then convert explicitly to T. + // Forwarding as T (the old behaviour) made the call ill-formed for any const-qualified + // lvalue of type T: forward requires a non-const T&, and a T&& cannot bind to a + // reference-related const lvalue. The explicit conversion also keeps narrowing + // initialisers (e.g. make_deque(0, 1)) working, which plain forwarding into the + // braced initialiser list would reject. + return {static_cast(etl::forward(values))...}; } #endif diff --git a/test/test_array.cpp b/test/test_array.cpp index f76e617f..8c8fa168 100644 --- a/test/test_array.cpp +++ b/test/test_array.cpp @@ -950,6 +950,69 @@ namespace } #endif + //************************************************************************* +#if ETL_HAS_INITIALIZER_LIST + // Arguments that are const-qualified lvalues of the element type used to be rejected: + // the old implementation forwarded each argument as T, and forward cannot accept a + // const T lvalue (it requires a non-const T&, and T&& cannot bind to a reference-related + // const lvalue). + TEST(test_make_array_from_const_lvalues_of_element_type) + { + static const char static_const_lvalue = 42; + const char local_const_lvalue = 43; + char mutable_lvalue = 44; + + auto data = etl::make_array(static_const_lvalue, local_const_lvalue, mutable_lvalue); + + using Type = etl::remove_reference_t; + CHECK((std::is_same::value)); + + CHECK_EQUAL(42, data[0]); + CHECK_EQUAL(43, data[1]); + CHECK_EQUAL(44, data[2]); + } +#endif + + //************************************************************************* +#if ETL_HAS_INITIALIZER_LIST + // The arguments are converted to the element type with static_cast, so narrowing + // initialisers (int literals and int lvalues narrowed to char) must keep working. + // Plain forwarding into the braced initialiser list would reject them. + TEST(test_make_array_from_narrowing_values) + { + static const int static_const_int = 45; + const int local_const_int = 46; + int mutable_int = 47; + + auto data = etl::make_array(0, 1, static_const_int, local_const_int, mutable_int); + + using Type = etl::remove_reference_t; + CHECK((std::is_same::value)); + + CHECK_EQUAL(0, data[0]); + CHECK_EQUAL(1, data[1]); + CHECK_EQUAL(45, data[2]); + CHECK_EQUAL(46, data[3]); + CHECK_EQUAL(47, data[4]); + } +#endif + + //************************************************************************* +#if ETL_HAS_INITIALIZER_LIST && ETL_USING_CPP14 + TEST(test_make_array_is_constexpr) + { + static constexpr unsigned char constexpr_value = 0x18U; + + constexpr auto data = etl::make_array(constexpr_value, constexpr_value); + + static_assert(data.size() == 2U, "make_array size"); + static_assert(data[0] == 0x18U, "make_array element"); + + CHECK_EQUAL(0x18U, data[0]); + CHECK_EQUAL(0x18U, data[1]); + } +#endif + #if ETL_USING_CPP14 //************************************************************************* using Array = etl::array; diff --git a/test/test_deque.cpp b/test/test_deque.cpp index a09f67d5..85365284 100644 --- a/test/test_deque.cpp +++ b/test/test_deque.cpp @@ -2299,6 +2299,53 @@ namespace } #endif + //************************************************************************* +#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST + // Arguments that are const-qualified lvalues of the element type used to be rejected: + // the old implementation forwarded each argument as T, and forward cannot accept a + // const T lvalue (it requires a non-const T&, and T&& cannot bind to a reference-related + // const lvalue). + TEST(test_make_deque_from_const_lvalues_of_element_type) + { + static const char static_const_lvalue = 42; + const char local_const_lvalue = 43; + char mutable_lvalue = 44; + + auto data = etl::make_deque(static_const_lvalue, local_const_lvalue, mutable_lvalue); + + using Type = etl::remove_reference_t; + CHECK((std::is_same::value)); + + CHECK_EQUAL(42, data[0]); + CHECK_EQUAL(43, data[1]); + CHECK_EQUAL(44, data[2]); + } +#endif + + //************************************************************************* +#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST + // The arguments are converted to the element type with static_cast, so narrowing + // initialisers (int literals and int lvalues narrowed to char) must keep working. + // Plain forwarding into the braced initialiser list would reject them. + TEST(test_make_deque_from_narrowing_values) + { + static const int static_const_int = 45; + const int local_const_int = 46; + int mutable_int = 47; + + auto data = etl::make_deque(0, 1, static_const_int, local_const_int, mutable_int); + + using Type = etl::remove_reference_t; + CHECK((std::is_same::value)); + + CHECK_EQUAL(0, data[0]); + CHECK_EQUAL(1, data[1]); + CHECK_EQUAL(45, data[2]); + CHECK_EQUAL(46, data[3]); + CHECK_EQUAL(47, data[4]); + } +#endif + //************************************************************************* TEST(test_fill) { diff --git a/test/test_flat_map.cpp b/test/test_flat_map.cpp index c88bedd9..ae9ddbdd 100644 --- a/test/test_flat_map.cpp +++ b/test/test_flat_map.cpp @@ -1544,6 +1544,29 @@ namespace } #endif + //************************************************************************* +#if ETL_HAS_INITIALIZER_LIST + // Arguments that are const-qualified lvalues of the pair type must be + // accepted. Guards against the defect fixed for make_array and make_deque, + // which forwarded each argument as the element type rather than as its own + // deduced type and so rejected const lvalues. + TEST_FIXTURE(SetupFixture, test_make_flat_map_from_const_lvalues_of_pair_type) + { + using Pair = ETL_OR_STD::pair; + + static const Pair static_const_lvalue('a', 0); + const Pair local_const_lvalue('b', 1); + Pair mutable_lvalue('c', 2); + + auto data = etl::make_flat_map(static_const_lvalue, local_const_lvalue, mutable_lvalue); + + CHECK_EQUAL(3U, data.size()); + CHECK_EQUAL(0, data.at('a')); + CHECK_EQUAL(1, data.at('b')); + CHECK_EQUAL(2, data.at('c')); + } +#endif + //************************************************************************* TEST_FIXTURE(SetupFixture, test_contains) { diff --git a/test/test_flat_multimap.cpp b/test/test_flat_multimap.cpp index 41962cc2..d1f3ccd9 100644 --- a/test/test_flat_multimap.cpp +++ b/test/test_flat_multimap.cpp @@ -1300,6 +1300,29 @@ namespace } #endif + //************************************************************************* +#if ETL_HAS_INITIALIZER_LIST + // Arguments that are const-qualified lvalues of the pair type must be + // accepted. Guards against the defect fixed for make_array and make_deque, + // which forwarded each argument as the element type rather than as its own + // deduced type and so rejected const lvalues. + TEST_FIXTURE(SetupFixture, test_make_flat_multimap_from_const_lvalues_of_pair_type) + { + using Pair = ETL_OR_STD::pair; + + static const Pair static_const_lvalue('a', 0); + const Pair local_const_lvalue('b', 1); + Pair mutable_lvalue('c', 2); + + auto data = etl::make_flat_multimap(static_const_lvalue, local_const_lvalue, mutable_lvalue); + + CHECK_EQUAL(3U, data.size()); + CHECK_EQUAL(0, data.find('a')->second); + CHECK_EQUAL(1, data.find('b')->second); + CHECK_EQUAL(2, data.find('c')->second); + } +#endif + //************************************************************************* TEST_FIXTURE(SetupFixture, test_contains) { diff --git a/test/test_flat_multiset.cpp b/test/test_flat_multiset.cpp index 694bb802..2d91748e 100644 --- a/test/test_flat_multiset.cpp +++ b/test/test_flat_multiset.cpp @@ -1293,6 +1293,34 @@ namespace } #endif + //************************************************************************* +#if ETL_HAS_INITIALIZER_LIST + // Arguments that are const-qualified lvalues of the key type must be + // accepted. Guards against the defect fixed for make_array and make_deque, + // which forwarded each argument as the element type rather than as its own + // deduced type and so rejected const lvalues. + TEST_FIXTURE(SetupFixture, test_make_flat_multiset_from_const_lvalues_of_key_type) + { + static const char static_const_lvalue = 42; + const char local_const_lvalue = 43; + char mutable_lvalue = 44; + + auto data = etl::make_flat_multiset(static_const_lvalue, local_const_lvalue, mutable_lvalue); + + auto v = *data.begin(); + using Type = decltype(v); + CHECK((std::is_same::value)); + + decltype(data)::const_iterator itr = data.begin(); + + CHECK_EQUAL(42, *itr); + ++itr; + CHECK_EQUAL(43, *itr); + ++itr; + CHECK_EQUAL(44, *itr); + } +#endif + //************************************************************************* TEST_FIXTURE(SetupFixture, test_contains) { diff --git a/test/test_flat_set.cpp b/test/test_flat_set.cpp index 1355f8c0..7930c72d 100644 --- a/test/test_flat_set.cpp +++ b/test/test_flat_set.cpp @@ -1292,6 +1292,34 @@ namespace } #endif + //************************************************************************* +#if ETL_HAS_INITIALIZER_LIST + // Arguments that are const-qualified lvalues of the key type must be + // accepted. Guards against the defect fixed for make_array and make_deque, + // which forwarded each argument as the element type rather than as its own + // deduced type and so rejected const lvalues. + TEST_FIXTURE(SetupFixture, test_make_flat_set_from_const_lvalues_of_key_type) + { + static const char static_const_lvalue = 42; + const char local_const_lvalue = 43; + char mutable_lvalue = 44; + + auto data = etl::make_flat_set(static_const_lvalue, local_const_lvalue, mutable_lvalue); + + auto v = *data.begin(); + using Type = decltype(v); + CHECK((std::is_same::value)); + + decltype(data)::const_iterator itr = data.begin(); + + CHECK_EQUAL(42, *itr); + ++itr; + CHECK_EQUAL(43, *itr); + ++itr; + CHECK_EQUAL(44, *itr); + } +#endif + //************************************************************************* TEST_FIXTURE(SetupFixture, test_contains) { diff --git a/test/test_forward_list.cpp b/test/test_forward_list.cpp index 3f805b7f..8687bf82 100644 --- a/test/test_forward_list.cpp +++ b/test/test_forward_list.cpp @@ -1445,6 +1445,117 @@ namespace } #endif + //************************************************************************* +#if ETL_HAS_INITIALIZER_LIST + // Arguments that are const-qualified lvalues must be accepted and must not + // affect the deduced element type. Guards against the defect fixed for + // make_array and make_deque, which forwarded each argument as the element + // type rather than as its own deduced type and so rejected const lvalues. + TEST(test_make_forward_list_from_const_lvalues_of_element_type) + { + static const char static_const_lvalue = 42; + const char local_const_lvalue = 43; + char mutable_lvalue = 44; + + auto data = etl::make_forward_list(static_const_lvalue, local_const_lvalue, mutable_lvalue); + + auto v = *data.begin(); + using Type = decltype(v); + CHECK((std::is_same::value)); + + decltype(data)::const_iterator itr = data.begin(); + + CHECK_EQUAL(42, *itr++); + CHECK_EQUAL(43, *itr++); + CHECK_EQUAL(44, *itr++); + } +#endif + + //************************************************************************* +#if ETL_HAS_INITIALIZER_LIST + TEST(test_make_forward_list_common_type_from_mixed_types) + { + auto data = etl::make_forward_list(1, 2L, 3); + + CHECK((std::is_same, decltype(data)>::value)); + + auto itr = data.begin(); + CHECK_EQUAL(1L, *itr++); + CHECK_EQUAL(2L, *itr++); + CHECK_EQUAL(3L, *itr++); + } +#endif + + //************************************************************************* +#if ETL_HAS_INITIALIZER_LIST + struct CopyMoveCounted + { + explicit CopyMoveCounted(int value_) + : value(value_) + { + } + + CopyMoveCounted(const CopyMoveCounted& other) + : value(other.value) + { + ++copy_count; + } + + CopyMoveCounted(CopyMoveCounted&& other) + : value(other.value) + { + ++move_count; + } + + int value; + + static size_t copy_count; + static size_t move_count; + }; + + size_t CopyMoveCounted::copy_count = 0; + size_t CopyMoveCounted::move_count = 0; + + // The arguments must be forwarded into the initializer list, not taken by + // value: a by-value parameter pack would cost an extra move per argument + // (the defect fixed for make_list). Each element is then copied from the + // initializer_list backing array into its node, which is why lvalue + // arguments count two copies. + TEST(test_make_forward_list_argument_copy_and_move_counts) + { + const CopyMoveCounted const_lvalue(1); + CopyMoveCounted mutable_lvalue(2); + + CopyMoveCounted::copy_count = 0; + CopyMoveCounted::move_count = 0; + + auto data = etl::make_forward_list(const_lvalue, mutable_lvalue); + + CHECK_EQUAL(4U, CopyMoveCounted::copy_count); + #if ETL_USING_CPP17 + // The exact move counts rely on guaranteed copy elision. Before C++17 the + // returned forward_list may be move-constructed once more, which moves each + // element, so only the copy counts are checked there. + CHECK_EQUAL(0U, CopyMoveCounted::move_count); + #endif + + CopyMoveCounted::copy_count = 0; + CopyMoveCounted::move_count = 0; + + auto data2 = etl::make_forward_list(CopyMoveCounted(3)); + + CHECK_EQUAL(1U, CopyMoveCounted::copy_count); + #if ETL_USING_CPP17 + CHECK_EQUAL(1U, CopyMoveCounted::move_count); + #endif + + auto itr = data.begin(); + CHECK_EQUAL(1, (*itr++).value); + CHECK_EQUAL(2, (*itr).value); + CHECK_EQUAL(3, data2.begin()->value); + } +#endif + //************************************************************************* TEST(test_forward_list_exception_types) { diff --git a/test/test_indirect_vector.cpp b/test/test_indirect_vector.cpp index f0a5d54e..2d8033cd 100644 --- a/test/test_indirect_vector.cpp +++ b/test/test_indirect_vector.cpp @@ -1621,5 +1621,28 @@ namespace CHECK(std::equal(blank_data.begin(), blank_data.end(), data.begin())); } + + //************************************************************************* +#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST + // Arguments that are const-qualified lvalues must be accepted and must not + // affect the deduced element type. Guards against the defect fixed for + // make_array and make_deque, which forwarded each argument as the element + // type rather than as its own deduced type and so rejected const lvalues. + TEST(test_make_indirect_vector_from_const_lvalues_of_element_type) + { + static const char static_const_lvalue = 42; + const char local_const_lvalue = 43; + char mutable_lvalue = 44; + + auto data = etl::make_indirect_vector(static_const_lvalue, local_const_lvalue, mutable_lvalue); + + using Type = typename std::remove_reference::type; + CHECK((std::is_same::value)); + + CHECK_EQUAL(42, data[0]); + CHECK_EQUAL(43, data[1]); + CHECK_EQUAL(44, data[2]); + } +#endif } } // namespace diff --git a/test/test_map.cpp b/test/test_map.cpp index c57b5b5e..9ce01897 100644 --- a/test/test_map.cpp +++ b/test/test_map.cpp @@ -1765,6 +1765,29 @@ namespace } #endif + //************************************************************************* +#if ETL_HAS_INITIALIZER_LIST + // Arguments that are const-qualified lvalues of the pair type must be + // accepted. Guards against the defect fixed for make_array and make_deque, + // which forwarded each argument as the element type rather than as its own + // deduced type and so rejected const lvalues. + TEST_FIXTURE(SetupFixture, test_make_map_from_const_lvalues_of_pair_type) + { + using Pair = ETL_OR_STD::pair; + + static const Pair static_const_lvalue('a', 0); + const Pair local_const_lvalue('b', 1); + Pair mutable_lvalue('c', 2); + + auto data = etl::make_map(static_const_lvalue, local_const_lvalue, mutable_lvalue); + + CHECK_EQUAL(3U, data.size()); + CHECK_EQUAL(0, data.at('a')); + CHECK_EQUAL(1, data.at('b')); + CHECK_EQUAL(2, data.at('c')); + } +#endif + //************************************************************************* TEST_FIXTURE(SetupFixture, test_contains) { diff --git a/test/test_multimap.cpp b/test/test_multimap.cpp index 86f9af0f..4273932b 100644 --- a/test/test_multimap.cpp +++ b/test/test_multimap.cpp @@ -1685,6 +1685,29 @@ namespace } #endif + //************************************************************************* +#if ETL_HAS_INITIALIZER_LIST + // Arguments that are const-qualified lvalues of the pair type must be + // accepted. Guards against the defect fixed for make_array and make_deque, + // which forwarded each argument as the element type rather than as its own + // deduced type and so rejected const lvalues. + TEST_FIXTURE(SetupFixture, test_make_multimap_from_const_lvalues_of_pair_type) + { + using Pair = ETL_OR_STD::pair; + + static const Pair static_const_lvalue('a', 0); + const Pair local_const_lvalue('b', 1); + Pair mutable_lvalue('c', 2); + + auto data = etl::make_multimap(static_const_lvalue, local_const_lvalue, mutable_lvalue); + + CHECK_EQUAL(3U, data.size()); + CHECK_EQUAL(0, data.find('a')->second); + CHECK_EQUAL(1, data.find('b')->second); + CHECK_EQUAL(2, data.find('c')->second); + } +#endif + //************************************************************************* TEST_FIXTURE(SetupFixture, test_contains_with_transparent_comparator) { diff --git a/test/test_multiset.cpp b/test/test_multiset.cpp index fcbae16a..7a31a65f 100644 --- a/test/test_multiset.cpp +++ b/test/test_multiset.cpp @@ -1608,6 +1608,34 @@ namespace } #endif + //************************************************************************* +#if ETL_HAS_INITIALIZER_LIST + // Arguments that are const-qualified lvalues of the key type must be + // accepted. Guards against the defect fixed for make_array and make_deque, + // which forwarded each argument as the element type rather than as its own + // deduced type and so rejected const lvalues. + TEST_FIXTURE(SetupFixture, test_make_multiset_from_const_lvalues_of_key_type) + { + static const char static_const_lvalue = 42; + const char local_const_lvalue = 43; + char mutable_lvalue = 44; + + auto data = etl::make_multiset(static_const_lvalue, local_const_lvalue, mutable_lvalue); + + auto v = *data.begin(); + using Type = decltype(v); + CHECK((std::is_same::value)); + + decltype(data)::const_iterator itr = data.begin(); + + CHECK_EQUAL(42, *itr); + ++itr; + CHECK_EQUAL(43, *itr); + ++itr; + CHECK_EQUAL(44, *itr); + } +#endif + //************************************************************************* TEST_FIXTURE(SetupFixture, test_contains) { diff --git a/test/test_set.cpp b/test/test_set.cpp index 863325c0..e23ca03a 100644 --- a/test/test_set.cpp +++ b/test/test_set.cpp @@ -1465,6 +1465,34 @@ namespace } #endif + //************************************************************************* +#if ETL_HAS_INITIALIZER_LIST + // Arguments that are const-qualified lvalues of the key type must be + // accepted. Guards against the defect fixed for make_array and make_deque, + // which forwarded each argument as the element type rather than as its own + // deduced type and so rejected const lvalues. + TEST_FIXTURE(SetupFixture, test_make_set_from_const_lvalues_of_key_type) + { + static const char static_const_lvalue = 42; + const char local_const_lvalue = 43; + char mutable_lvalue = 44; + + auto data = etl::make_set(static_const_lvalue, local_const_lvalue, mutable_lvalue); + + auto v = *data.begin(); + using Type = decltype(v); + CHECK((std::is_same::value)); + + decltype(data)::const_iterator itr = data.begin(); + + CHECK_EQUAL(42, *itr); + ++itr; + CHECK_EQUAL(43, *itr); + ++itr; + CHECK_EQUAL(44, *itr); + } +#endif + //************************************************************************* TEST_FIXTURE(SetupFixture, test_contains) { diff --git a/test/test_unordered_map.cpp b/test/test_unordered_map.cpp index 793343eb..57ccd928 100644 --- a/test/test_unordered_map.cpp +++ b/test/test_unordered_map.cpp @@ -1484,5 +1484,28 @@ namespace CHECK_TRUE(data.contains("FF")); CHECK_FALSE(data.contains(not_inserted)); } + + //************************************************************************* +#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST + // Arguments that are const-qualified lvalues of the pair type must be + // accepted. Guards against the defect fixed for make_array and make_deque, + // which forwarded each argument as the element type rather than as its own + // deduced type and so rejected const lvalues. + TEST(test_make_unordered_map_from_const_lvalues_of_pair_type) + { + using Pair = ETL_OR_STD::pair; + + static const Pair static_const_lvalue('a', 0); + const Pair local_const_lvalue('b', 1); + Pair mutable_lvalue('c', 2); + + auto data = etl::make_unordered_map(static_const_lvalue, local_const_lvalue, mutable_lvalue); + + CHECK_EQUAL(3U, data.size()); + CHECK_EQUAL(0, data.at('a')); + CHECK_EQUAL(1, data.at('b')); + CHECK_EQUAL(2, data.at('c')); + } +#endif } } // namespace diff --git a/test/test_unordered_multimap.cpp b/test/test_unordered_multimap.cpp index bf2c2aa6..2207f642 100644 --- a/test/test_unordered_multimap.cpp +++ b/test/test_unordered_multimap.cpp @@ -1243,5 +1243,28 @@ namespace CHECK_TRUE(data.contains("FF")); CHECK_FALSE(data.contains(not_inserted)); } + + //************************************************************************* +#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST + // Arguments that are const-qualified lvalues of the pair type must be + // accepted. Guards against the defect fixed for make_array and make_deque, + // which forwarded each argument as the element type rather than as its own + // deduced type and so rejected const lvalues. + TEST(test_make_unordered_multimap_from_const_lvalues_of_pair_type) + { + using Pair = ETL_OR_STD::pair; + + static const Pair static_const_lvalue('a', 0); + const Pair local_const_lvalue('b', 1); + Pair mutable_lvalue('c', 2); + + auto data = etl::make_unordered_multimap(static_const_lvalue, local_const_lvalue, mutable_lvalue); + + CHECK_EQUAL(3U, data.size()); + CHECK_EQUAL(0, data.find('a')->second); + CHECK_EQUAL(1, data.find('b')->second); + CHECK_EQUAL(2, data.find('c')->second); + } +#endif } } // namespace diff --git a/test/test_unordered_multiset.cpp b/test/test_unordered_multiset.cpp index 9a05aca8..862baa6c 100644 --- a/test/test_unordered_multiset.cpp +++ b/test/test_unordered_multiset.cpp @@ -1113,5 +1113,26 @@ namespace CHECK_TRUE(data.contains("FF")); CHECK_FALSE(data.contains(not_inserted)); } + + //************************************************************************* +#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST + // Arguments that are const-qualified lvalues of the key type must be + // accepted. Guards against the defect fixed for make_array and make_deque, + // which forwarded each argument as the element type rather than as its own + // deduced type and so rejected const lvalues. + TEST(test_make_unordered_multiset_from_const_lvalues_of_key_type) + { + static const char static_const_lvalue = 42; + const char local_const_lvalue = 43; + char mutable_lvalue = 44; + + auto data = etl::make_unordered_multiset(static_const_lvalue, local_const_lvalue, mutable_lvalue); + + CHECK_EQUAL(3U, data.size()); + CHECK_EQUAL(1U, data.count(42)); + CHECK_EQUAL(1U, data.count(43)); + CHECK_EQUAL(1U, data.count(44)); + } +#endif } } // namespace diff --git a/test/test_unordered_set.cpp b/test/test_unordered_set.cpp index da0831c8..cd959a2a 100644 --- a/test/test_unordered_set.cpp +++ b/test/test_unordered_set.cpp @@ -1122,6 +1122,27 @@ namespace CHECK_TRUE(data.contains("FF")); CHECK_FALSE(data.contains(not_inserted)); } + + //************************************************************************* +#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST + // Arguments that are const-qualified lvalues of the key type must be + // accepted. Guards against the defect fixed for make_array and make_deque, + // which forwarded each argument as the element type rather than as its own + // deduced type and so rejected const lvalues. + TEST(test_make_unordered_set_from_const_lvalues_of_key_type) + { + static const char static_const_lvalue = 42; + const char local_const_lvalue = 43; + char mutable_lvalue = 44; + + auto data = etl::make_unordered_set(static_const_lvalue, local_const_lvalue, mutable_lvalue); + + CHECK_EQUAL(3U, data.size()); + CHECK_EQUAL(1U, data.count(42)); + CHECK_EQUAL(1U, data.count(43)); + CHECK_EQUAL(1U, data.count(44)); + } +#endif } #include "etl/private/diagnostic_pop.h" } // namespace diff --git a/test/test_vector.cpp b/test/test_vector.cpp index 026e2176..0340c4cb 100644 --- a/test/test_vector.cpp +++ b/test/test_vector.cpp @@ -1567,6 +1567,29 @@ namespace } #endif + //************************************************************************* +#if ETL_HAS_INITIALIZER_LIST + // Arguments that are const-qualified lvalues must be accepted and must not + // affect the deduced element type. Guards against the defect fixed for + // make_array and make_deque, which forwarded each argument as the element + // type rather than as its own deduced type and so rejected const lvalues. + TEST(test_make_vector_from_const_lvalues_of_element_type) + { + static const char static_const_lvalue = 42; + const char local_const_lvalue = 43; + char mutable_lvalue = 44; + + auto data = etl::make_vector(static_const_lvalue, local_const_lvalue, mutable_lvalue); + + using Type = typename std::remove_reference::type; + CHECK((std::is_same::value)); + + CHECK_EQUAL(42, data[0]); + CHECK_EQUAL(43, data[1]); + CHECK_EQUAL(44, data[2]); + } +#endif + //************************************************************************* TEST(test_fill) {