Merge pull request #17 from furfurylic/conditional_explicit_replace_if_xxxx
Make ctors of replace_if_conversion_failed and replace_if_skipped conditionally explicit
This commit is contained in:
commit
d473af2e21
|
@ -2,7 +2,7 @@
|
|||
<?xml-stylesheet type="text/xsl" href="Commata.xsl"?>
|
||||
<document>
|
||||
<title>Specification of Commata, which is just another C++17 CSV parser</title>
|
||||
<signature>2024-08-19 (UTC)</signature>
|
||||
<signature>2024-08-23 (UTC)</signature>
|
||||
|
||||
<section id="introduction">
|
||||
<name>Introduction</name>
|
||||
|
@ -1921,7 +1921,7 @@ namespace commata {
|
|||
|
||||
<c>// <n><xref id="replace_if_conversion_failed.cons"/>, construct/copy/destroy:</n></c>
|
||||
template <class All = T>
|
||||
explicit replace_if_conversion_failed(const All& for_all = All()) noexcept(<nc>see below</nc>);
|
||||
<nc>EXPLICIT</nc> replace_if_conversion_failed(const All& for_all = All()) noexcept(<nc>see below</nc>);
|
||||
template <class Empty, class AllButEmpty>
|
||||
replace_if_conversion_failed(Empty&& on_empty,
|
||||
const AllButEmpty& for_all_but_empty) noexcept(<nc>see below</nc>);
|
||||
|
@ -2036,11 +2036,12 @@ static constexpr std::size_t size = <nc>see below</nc>;
|
|||
<code-item>
|
||||
<code>
|
||||
template <class All = T>
|
||||
explicit replace_if_conversion_failed(const All& for_all = All()) noexcept(<nc>see below</nc>);
|
||||
<nc>EXPLICIT</nc> replace_if_conversion_failed(const All& for_all = All()) noexcept(<nc>see below</nc>);
|
||||
</code>
|
||||
<effects>Arranges all configurable replacement actions from <c>for_all</c>.</effects>
|
||||
<remark>This overload shall not participate in overload resolution unless <c><nc>IS_ACCEPTABLE</nc><const All&></c> is <c>true</c>.
|
||||
The expression inside <c>noexcept</c> is equvalent to <c><nc>IS_NOTHROW_ACCEPTABLE</nc><T, const All&></c>.</remark>
|
||||
The expression inside <c>noexcept</c> is equvalent to <c><nc>IS_NOTHROW_ACCEPTABLE</nc><T, const All&></c>.
|
||||
This constructor is explicit if and only if <c>std::is_convertible_v<const All&, T></c> is <c>false</c>.</remark>
|
||||
</code-item>
|
||||
|
||||
<code-item>
|
||||
|
@ -6951,7 +6952,7 @@ namespace commata {
|
|||
|
||||
<c>// <n><xref id="replace_if_skipped.cons"/>, construct/copy/destroy:</n></c>
|
||||
template <class U = T>
|
||||
explicit replace_if_skipped(U&& u = std::decay_t<U>()) noexcept(<nc>see below</nc>);
|
||||
<nc>EXPLICIT</nc> replace_if_skipped(U&& u = std::decay_t<U>()) noexcept(<nc>see below</nc>);
|
||||
explicit replace_if_skipped(replacement_fail_t) noexcept;
|
||||
explicit replace_if_skipped(replacement_ignore_t) noexcept;
|
||||
replace_if_skipped(const replace_if_skipped& other) noexcept(<nc>see below</nc>);
|
||||
|
@ -6990,14 +6991,15 @@ namespace commata {
|
|||
<code-item>
|
||||
<code>
|
||||
template <class U = T>
|
||||
explicit replace_if_skipped(U&& u = std::decay_t<U>()) noexcept(<nc>see below</nc>);
|
||||
<nc>EXPLICIT</nc> replace_if_skipped(U&& u = std::decay_t<U>()) noexcept(<nc>see below</nc>);
|
||||
</code>
|
||||
<effects>Configures the replacement action to be <c>copy</c> with an object of <c>T</c> constructed from <c>std::forward<U>(u)</c>.</effects>
|
||||
<remark>This constructor shall not participate in overload resolution unless <c>std::is_constructible_v<T, U></c> is <c>true</c>,
|
||||
<c>std::is_base_of_v<replace_if_skipped<T>, std::decay<U>></c> is <c>false</c>,
|
||||
<c>std::is_base_of_v<replacement_fail_t, std::decay<U>></c> is <c>false</c>, and
|
||||
<c>std::is_base_of_v<replacement_ignore_t, std::decay<U>></c> is <c>false</c>.
|
||||
The expression inside <c>noexcept</c> is equivalent to <c>std::is_nothrow_constructible_v<T, U></c>.</remark>
|
||||
The expression inside <c>noexcept</c> is equivalent to <c>std::is_nothrow_constructible_v<T, U></c>.
|
||||
This constructor is explicit if and only if <c>std::is_convertible_v<U&&, T></c> is <c>false</c>.</remark>
|
||||
</code-item>
|
||||
|
||||
<code-item>
|
||||
|
|
|
@ -235,6 +235,7 @@ public:
|
|||
template <class U = T,
|
||||
std::enable_if_t<
|
||||
std::is_constructible_v<T, U>
|
||||
&& !std::is_convertible_v<U&&, T>
|
||||
&& !(std::is_base_of_v<replace_if_skipped, std::decay_t<U>>
|
||||
|| std::is_base_of_v<replacement_fail_t, std::decay_t<U>>
|
||||
|| std::is_base_of_v<replacement_ignore_t, std::decay_t<U>>)>*
|
||||
|
@ -244,6 +245,19 @@ public:
|
|||
store_(generic_args_t(), std::forward<U>(u))
|
||||
{}
|
||||
|
||||
template <class U = T,
|
||||
std::enable_if_t<
|
||||
std::is_constructible_v<T, U>
|
||||
&& std::is_convertible_v<U&&, T>
|
||||
&& !(std::is_base_of_v<replace_if_skipped, std::decay_t<U>>
|
||||
|| std::is_base_of_v<replacement_fail_t, std::decay_t<U>>
|
||||
|| std::is_base_of_v<replacement_ignore_t, std::decay_t<U>>)>*
|
||||
= nullptr>
|
||||
replace_if_skipped(U&& u = std::decay_t<U>())
|
||||
noexcept(std::is_nothrow_constructible_v<T, U>) :
|
||||
store_(generic_args_t(), std::forward<U>(u))
|
||||
{}
|
||||
|
||||
explicit replace_if_skipped(replacement_fail_t) noexcept :
|
||||
store_(detail::replace_mode::fail)
|
||||
{}
|
||||
|
|
|
@ -830,11 +830,19 @@ template <class T>
|
|||
struct base<T, 3> : base_base<T, 3>
|
||||
{
|
||||
template <class All = T,
|
||||
std::enable_if_t<is_acceptable_arg_v<T, const All&>>* = nullptr>
|
||||
std::enable_if_t<!std::is_convertible_v<const All&, T>
|
||||
&& is_acceptable_arg_v<T, const All&>>* = nullptr>
|
||||
explicit base(const All& for_all = All()) :
|
||||
base(for_all, for_all, for_all)
|
||||
{}
|
||||
|
||||
template <class All = T,
|
||||
std::enable_if_t<std::is_convertible_v<const All&, T>
|
||||
&& is_acceptable_arg_v<T, const All&>>* = nullptr>
|
||||
base(const All& for_all = All()) :
|
||||
base(for_all, for_all, for_all)
|
||||
{}
|
||||
|
||||
template <class Empty, class AllButEmpty,
|
||||
std::enable_if_t<
|
||||
is_acceptable_arg_v<T, Empty&&>
|
||||
|
@ -869,11 +877,19 @@ template <class T>
|
|||
struct base<T, 4> : base_base<T, 4>
|
||||
{
|
||||
template <class All = T,
|
||||
std::enable_if_t<is_acceptable_arg_v<T, const All&>>* = nullptr>
|
||||
std::enable_if_t<!std::is_convertible_v<const All&, T>
|
||||
&& is_acceptable_arg_v<T, const All&>>* = nullptr>
|
||||
explicit base(const All& for_all = All()) :
|
||||
base(for_all, for_all, for_all, for_all)
|
||||
{}
|
||||
|
||||
template <class All = T,
|
||||
std::enable_if_t<std::is_convertible_v<const All&, T>
|
||||
&& is_acceptable_arg_v<T, const All&>>* = nullptr>
|
||||
base(const All& for_all = All()) :
|
||||
base(for_all, for_all, for_all, for_all)
|
||||
{}
|
||||
|
||||
template <class Empty, class AllButEmpty,
|
||||
std::enable_if_t<
|
||||
is_acceptable_arg_v<T, Empty&&>
|
||||
|
@ -925,11 +941,19 @@ template <class T>
|
|||
struct base<T, 5> : base_base<T, 5>
|
||||
{
|
||||
template <class All = T,
|
||||
std::enable_if_t<is_acceptable_arg_v<T, const All&>>* = nullptr>
|
||||
std::enable_if_t<!std::is_convertible_v<const All&, T>
|
||||
&& is_acceptable_arg_v<T, const All&>>* = nullptr>
|
||||
explicit base(const All& for_all = All()) :
|
||||
base(for_all, for_all, for_all, for_all, for_all)
|
||||
{}
|
||||
|
||||
template <class All = T,
|
||||
std::enable_if_t<std::is_convertible_v<const All&, T>
|
||||
&& is_acceptable_arg_v<T, const All&>>* = nullptr>
|
||||
base(const All& for_all = All()) :
|
||||
base(for_all, for_all, for_all, for_all, for_all)
|
||||
{}
|
||||
|
||||
template <class Empty, class AllButEmpty,
|
||||
std::enable_if_t<
|
||||
is_acceptable_arg_v<T, Empty&&>
|
||||
|
|
|
@ -1270,6 +1270,25 @@ TEST_F(TestTableScannerReference, RecordEndScanner)
|
|||
ASSERT_EQ(-12345, v[3]);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct B
|
||||
{};
|
||||
|
||||
struct D : B
|
||||
{};
|
||||
|
||||
struct E
|
||||
{
|
||||
explicit E(const B&)
|
||||
{}
|
||||
};
|
||||
|
||||
static_assert(std::is_convertible_v<D, replace_if_skipped<B>>);
|
||||
static_assert(!std::is_convertible_v<B, replace_if_skipped<E>>);
|
||||
|
||||
} // end unnamed
|
||||
|
||||
struct TestReplaceIfSkipped : BaseTest
|
||||
{};
|
||||
|
||||
|
|
|
@ -164,6 +164,21 @@ namespace {
|
|||
|
||||
using ReplacedTypes = testing::Types<double, std::string>;
|
||||
|
||||
struct B
|
||||
{};
|
||||
|
||||
struct D : B
|
||||
{};
|
||||
|
||||
struct E
|
||||
{
|
||||
explicit E(const B&)
|
||||
{}
|
||||
};
|
||||
|
||||
static_assert(std::is_convertible_v<D, replace_if_conversion_failed<B>>);
|
||||
static_assert(!std::is_convertible_v<B, replace_if_conversion_failed<E>>);
|
||||
|
||||
} // end unnamed
|
||||
|
||||
TYPED_TEST_SUITE(TestReplaceIfConversionFailed, ReplacedTypes);
|
||||
|
|
Loading…
Reference in New Issue