added value type deduction to emplace() methods

also:
- minor CI work
This commit is contained in:
Mark Gillard 2022-05-09 00:18:19 +03:00
parent 27816dbbd1
commit 5eec04b951
10 changed files with 142 additions and 74 deletions

View File

@ -25,8 +25,6 @@ on:
- '**/workflows/**.yaml'
workflow_dispatch:
# This ensures that jobs get canceled when force-pushing
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
@ -36,36 +34,39 @@ jobs:
strategy:
fail-fast: false
matrix:
compiler: [ 'g++', 'clang' ]
type: [ 'debug', 'release' ]
compile_library: [ true, false ]
compiler:
- 'clang++'
- 'g++'
linker:
- 'lld'
type:
- 'debug'
- 'release'
compile_library:
- 'true'
- 'false'
runs-on: ubuntu-latest
container:
image: debian:testing
defaults:
run:
shell: sh
steps:
- name: Install dependencies
run: |
apt-get -y update
apt-get -y install --no-install-recommends ${{ matrix.compiler }} lld meson pkgconf git ca-certificates locales-all python3-pip
sudo apt -y update
if [ ${{ matrix.compiler }} = clang++ ]; then compiler=clang; else compiler=${{ matrix.compiler }}; fi
sudo apt -y install --no-install-recommends $compiler ${{ matrix.linker }} pkgconf git ca-certificates locales-all python3 python3-pip python3-setuptools python3-wheel ninja-build
sudo pip3 install --upgrade meson
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Check toml.hpp
run: |
pip3 install --upgrade --requirement tools/requirements.txt
sudo pip3 install --upgrade --requirement tools/requirements.txt
cd tools
./ci_single_header_check.py
python3 ci_single_header_check.py
- name: Configure Meson
run: |
if [ ${{ matrix.compiler }} = g++ ]; then linker=gold; else linker=lld; fi
CXX_LD=$linker meson setup build --buildtype=${{ matrix.type }} -Dcompile_library=${{ matrix.compile_library }} -Dpedantic=true -Dbuild_tests=true -Dbuild_examples=true -Dgenerate_cmake_config=false -Db_lto=false -Dubsan_examples=true -Dasan_examples=true
CXX=${{ matrix.compiler }} CXX_LD=${{ matrix.linker }} meson setup build --buildtype=${{ matrix.type }} -Dcompile_library=${{ matrix.compile_library }} -Dpedantic=true -Dbuild_tests=true -Dbuild_examples=true -Dgenerate_cmake_config=false -Db_lto=false -Dubsan_examples=true -Dasan_examples=true
- name: Build
run: meson compile -C build --jobs -1
@ -77,8 +78,12 @@ jobs:
strategy:
fail-fast: false
matrix:
type: [ 'debug', 'release' ]
compile_library: [ true ] # , false ] # ... header-only mode takes far too long on github's windows runner
type:
- 'debug'
- 'release'
compile_library:
- 'true'
# - 'false' # ... header-only mode takes far too long on github's windows runner
runs-on: windows-2022

View File

@ -13,6 +13,12 @@ template:
-->
## Unreleased
#### Additions:
- Added value type deduction to `emplace()` methods
<br><br>
## [v3.1.0](https://github.com/marzer/tomlplusplus/releases/tag/v3.1.0) - 2022-04-22

View File

@ -250,7 +250,7 @@ TOML_NAMESPACE_START
/// std::cout << arr << "\n";
///
/// // emplace elements
/// arr.emplace_back<std::string>("ten");
/// arr.emplace_back("ten");
/// arr.emplace_back<toml::array>(11, 12.0);
/// std::cout << arr << "\n";
/// \ecpp
@ -1484,10 +1484,13 @@ TOML_NAMESPACE_START
///
/// \remarks There is no difference between insert() and emplace()
/// for trivial value types (floats, ints, bools).
template <typename ElemType, typename... Args>
template <typename ElemType = void, typename... Args>
iterator emplace(const_iterator pos, Args&&... args)
{
using type = impl::unwrap_node<ElemType>;
static_assert(!impl::is_cvref<ElemType>, "ElemType may not be const, volatile, or a reference.");
using elem_type = std::conditional_t<std::is_void_v<ElemType>, impl::emplaced_type_of<Args&&...>, ElemType>;
using type = impl::unwrap_node<elem_type>;
static_assert((impl::is_native<type> || impl::is_one_of<type, table, array>)&&!impl::is_cvref<type>,
"Emplacement type parameter must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
@ -1577,23 +1580,24 @@ TOML_NAMESPACE_START
/// \eout
///
/// \tparam ElemType toml::table, toml::array, or a native TOML value type
/// \tparam ElemArgs Element constructor argument types.
/// \tparam Args Element constructor argument types.
/// \param args Arguments to forward to the elements's constructor.
///
/// \returns A reference to the newly-constructed element.
///
/// \remarks There is no difference between push_back() and emplace_back()
/// For trivial value types (floats, ints, bools).
template <typename ElemType, typename... ElemArgs>
decltype(auto) emplace_back(ElemArgs&&... args)
template <typename ElemType = void, typename... Args>
decltype(auto) emplace_back(Args&&... args)
{
static_assert(!impl::is_cvref<ElemType>, "ElemType may not be const, volatile, or a reference.");
using elem_type = std::conditional_t<std::is_void_v<ElemType>, impl::emplaced_type_of<Args&&...>, ElemType>;
static constexpr auto moving_node_ptr = std::is_same_v<ElemType, impl::node_ptr> //
&& sizeof...(ElemArgs) == 1u //
&& impl::first_is_same<impl::node_ptr&&, ElemArgs&&...>;
static constexpr auto moving_node_ptr = std::is_same_v<elem_type, impl::node_ptr> //
&& sizeof...(Args) == 1u //
&& impl::first_is_same<impl::node_ptr&&, Args&&...>;
using unwrapped_type = impl::unwrap_node<ElemType>;
using unwrapped_type = impl::unwrap_node<elem_type>;
static_assert(
moving_node_ptr //
@ -1603,12 +1607,12 @@ TOML_NAMESPACE_START
if constexpr (moving_node_ptr)
{
insert_at_back(static_cast<ElemArgs&&>(args)...);
insert_at_back(static_cast<Args&&>(args)...);
return *elems_.back();
}
else
{
auto ptr = new impl::wrap_node<unwrapped_type>{ static_cast<ElemArgs&&>(args)... };
auto ptr = new impl::wrap_node<unwrapped_type>{ static_cast<Args&&>(args)... };
insert_at_back(impl::node_ptr{ ptr });
return *ptr;
}

View File

@ -118,7 +118,7 @@ TOML_IMPL_NAMESPACE_START
template <typename T>
struct inserted_type_of_<inserter<T>, false>
{
using type = typename inserted_type_of_<T>::type;
using type = typename inserted_type_of_<remove_cvref<T>>::type;
};
template <typename T>
@ -133,6 +133,29 @@ TOML_IMPL_NAMESPACE_START
{
return node_ptr{ make_node_impl(static_cast<T&&>(val), flags) };
}
template <typename... T>
struct emplaced_type_of_
{
using type = void;
};
template <typename T>
struct emplaced_type_of_<T>
{
using type = std::conditional_t<is_one_of<T, node, node_view<node>, node_view<const node>>,
void,
typename inserted_type_of_<T>::type>;
};
template <typename T>
struct emplaced_type_of_<inserter<T>>
{
using type = typename emplaced_type_of_<remove_cvref<T>>::type;
};
template <typename... T>
using emplaced_type_of = typename emplaced_type_of_<remove_cvref<T>...>::type;
}
TOML_IMPL_NAMESPACE_END;
/// \endcond

View File

@ -1430,7 +1430,7 @@ TOML_NAMESPACE_START
///
/// \note This function has exactly the same semantics as [std::map::emplace_hint()](https://en.cppreference.com/w/cpp/container/map/emplace_hint).
TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
typename ValueType,
typename ValueType = void,
typename KeyType,
typename... ValueArgs)
iterator emplace_hint(const_iterator hint, KeyType&& key, ValueArgs&&... args)
@ -1440,23 +1440,25 @@ TOML_NAMESPACE_START
"TOML_ENABLE_WINDOWS_COMPAT enabled.");
static_assert(!impl::is_cvref<ValueType>, "ValueType may not be const, volatile, or a reference.");
using value_type =
std::conditional_t<std::is_void_v<ValueType>, impl::emplaced_type_of<ValueArgs&&...>, ValueType>;
if constexpr (impl::is_wide_string<KeyType>)
{
#if TOML_ENABLE_WINDOWS_COMPAT
return emplace_hint<ValueType>(hint,
impl::narrow(static_cast<KeyType&&>(key)),
static_cast<ValueArgs&&>(args)...);
return emplace_hint<value_type>(hint,
impl::narrow(static_cast<KeyType&&>(key)),
static_cast<ValueArgs&&>(args)...);
#else
static_assert(impl::dependent_false<KeyType>, "Evaluated unreachable branch!");
#endif
}
else
{
static constexpr auto moving_node_ptr = std::is_same_v<ValueType, impl::node_ptr> //
&& sizeof...(ValueArgs) == 1u //
static constexpr auto moving_node_ptr = std::is_same_v<value_type, impl::node_ptr> //
&& sizeof...(ValueArgs) == 1u //
&& impl::first_is_same<impl::node_ptr&&, ValueArgs&&...>;
using unwrapped_type = impl::unwrap_node<ValueType>;
using unwrapped_type = impl::unwrap_node<value_type>;
static_assert(moving_node_ptr //
|| impl::is_native<unwrapped_type> //
@ -1774,7 +1776,7 @@ TOML_NAMESPACE_START
///
/// \remark There is no difference between insert() and emplace() for trivial value types (floats, ints, bools).
TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
typename ValueType,
typename ValueType = void,
typename KeyType,
typename... ValueArgs)
std::pair<iterator, bool> emplace(KeyType&& key, ValueArgs&&... args)
@ -1784,18 +1786,21 @@ TOML_NAMESPACE_START
"TOML_ENABLE_WINDOWS_COMPAT enabled.");
static_assert(!impl::is_cvref<ValueType>, "ValueType may not be const, volatile, or a reference.");
using value_type =
std::conditional_t<std::is_void_v<ValueType>, impl::emplaced_type_of<ValueArgs&&...>, ValueType>;
if constexpr (impl::is_wide_string<KeyType>)
{
#if TOML_ENABLE_WINDOWS_COMPAT
return emplace<ValueType>(impl::narrow(static_cast<KeyType&&>(key)), static_cast<ValueArgs&&>(args)...);
return emplace<value_type>(impl::narrow(static_cast<KeyType&&>(key)),
static_cast<ValueArgs&&>(args)...);
#else
static_assert(impl::dependent_false<KeyType>, "Evaluated unreachable branch!");
#endif
}
else
{
using unwrapped_type = impl::unwrap_node<ValueType>;
using unwrapped_type = impl::unwrap_node<value_type>;
static_assert((impl::is_native<unwrapped_type> || impl::is_one_of<unwrapped_type, table, array>),
"ValueType argument of table::emplace() must be one "
"of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);

View File

@ -81,7 +81,6 @@
<ClInclude Include="include\toml++\toml.h" />
</ItemGroup>
<ItemGroup>
<None Include=".circleci\config.yml" />
<None Include=".clang-format" />
<None Include=".editorconfig" />
<None Include=".gitattributes" />

View File

@ -143,9 +143,6 @@
<None Include="LICENSE" />
<None Include="meson.build" />
<None Include="README.md" />
<None Include=".circleci\config.yml">
<Filter>.circleci</Filter>
</None>
<None Include="tools\ci_single_header_check.py">
<Filter>tools</Filter>
</None>
@ -241,9 +238,6 @@
</None>
</ItemGroup>
<ItemGroup>
<Filter Include=".circleci">
<UniqueIdentifier>{a987f817-4ce2-4fd7-9d86-50e619d8d97b}</UniqueIdentifier>
</Filter>
<Filter Include="docs">
<UniqueIdentifier>{5ed0949f-6855-4664-ad86-2b38ceeb400b}</UniqueIdentifier>
</Filter>

View File

@ -4921,7 +4921,7 @@ TOML_IMPL_NAMESPACE_START
template <typename T>
struct inserted_type_of_<inserter<T>, false>
{
using type = typename inserted_type_of_<T>::type;
using type = typename inserted_type_of_<remove_cvref<T>>::type;
};
template <typename T>
@ -4936,6 +4936,29 @@ TOML_IMPL_NAMESPACE_START
{
return node_ptr{ make_node_impl(static_cast<T&&>(val), flags) };
}
template <typename... T>
struct emplaced_type_of_
{
using type = void;
};
template <typename T>
struct emplaced_type_of_<T>
{
using type = std::conditional_t<is_one_of<T, node, node_view<node>, node_view<const node>>,
void,
typename inserted_type_of_<T>::type>;
};
template <typename T>
struct emplaced_type_of_<inserter<T>>
{
using type = typename emplaced_type_of_<remove_cvref<T>>::type;
};
template <typename... T>
using emplaced_type_of = typename emplaced_type_of_<remove_cvref<T>...>::type;
}
TOML_IMPL_NAMESPACE_END;
@ -5891,10 +5914,13 @@ TOML_NAMESPACE_START
return insert(pos, ilist.begin(), ilist.end(), flags);
}
template <typename ElemType, typename... Args>
template <typename ElemType = void, typename... Args>
iterator emplace(const_iterator pos, Args&&... args)
{
using type = impl::unwrap_node<ElemType>;
static_assert(!impl::is_cvref<ElemType>, "ElemType may not be const, volatile, or a reference.");
using elem_type = std::conditional_t<std::is_void_v<ElemType>, impl::emplaced_type_of<Args&&...>, ElemType>;
using type = impl::unwrap_node<elem_type>;
static_assert((impl::is_native<type> || impl::is_one_of<type, table, array>)&&!impl::is_cvref<type>,
"Emplacement type parameter must be one of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);
@ -5924,16 +5950,17 @@ TOML_NAMESPACE_START
emplace_back_if_not_empty_view(static_cast<ElemType&&>(val), flags);
}
template <typename ElemType, typename... ElemArgs>
decltype(auto) emplace_back(ElemArgs&&... args)
template <typename ElemType = void, typename... Args>
decltype(auto) emplace_back(Args&&... args)
{
static_assert(!impl::is_cvref<ElemType>, "ElemType may not be const, volatile, or a reference.");
using elem_type = std::conditional_t<std::is_void_v<ElemType>, impl::emplaced_type_of<Args&&...>, ElemType>;
static constexpr auto moving_node_ptr = std::is_same_v<ElemType, impl::node_ptr> //
&& sizeof...(ElemArgs) == 1u //
&& impl::first_is_same<impl::node_ptr&&, ElemArgs&&...>;
static constexpr auto moving_node_ptr = std::is_same_v<elem_type, impl::node_ptr> //
&& sizeof...(Args) == 1u //
&& impl::first_is_same<impl::node_ptr&&, Args&&...>;
using unwrapped_type = impl::unwrap_node<ElemType>;
using unwrapped_type = impl::unwrap_node<elem_type>;
static_assert(
moving_node_ptr //
@ -5943,12 +5970,12 @@ TOML_NAMESPACE_START
if constexpr (moving_node_ptr)
{
insert_at_back(static_cast<ElemArgs&&>(args)...);
insert_at_back(static_cast<Args&&>(args)...);
return *elems_.back();
}
else
{
auto ptr = new impl::wrap_node<unwrapped_type>{ static_cast<ElemArgs&&>(args)... };
auto ptr = new impl::wrap_node<unwrapped_type>{ static_cast<Args&&>(args)... };
insert_at_back(impl::node_ptr{ ptr });
return *ptr;
}
@ -7172,7 +7199,7 @@ TOML_NAMESPACE_START
public:
TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
typename ValueType,
typename ValueType = void,
typename KeyType,
typename... ValueArgs)
iterator emplace_hint(const_iterator hint, KeyType&& key, ValueArgs&&... args)
@ -7182,23 +7209,25 @@ TOML_NAMESPACE_START
"TOML_ENABLE_WINDOWS_COMPAT enabled.");
static_assert(!impl::is_cvref<ValueType>, "ValueType may not be const, volatile, or a reference.");
using value_type =
std::conditional_t<std::is_void_v<ValueType>, impl::emplaced_type_of<ValueArgs&&...>, ValueType>;
if constexpr (impl::is_wide_string<KeyType>)
{
#if TOML_ENABLE_WINDOWS_COMPAT
return emplace_hint<ValueType>(hint,
impl::narrow(static_cast<KeyType&&>(key)),
static_cast<ValueArgs&&>(args)...);
return emplace_hint<value_type>(hint,
impl::narrow(static_cast<KeyType&&>(key)),
static_cast<ValueArgs&&>(args)...);
#else
static_assert(impl::dependent_false<KeyType>, "Evaluated unreachable branch!");
#endif
}
else
{
static constexpr auto moving_node_ptr = std::is_same_v<ValueType, impl::node_ptr> //
&& sizeof...(ValueArgs) == 1u //
static constexpr auto moving_node_ptr = std::is_same_v<value_type, impl::node_ptr> //
&& sizeof...(ValueArgs) == 1u //
&& impl::first_is_same<impl::node_ptr&&, ValueArgs&&...>;
using unwrapped_type = impl::unwrap_node<ValueType>;
using unwrapped_type = impl::unwrap_node<value_type>;
static_assert(moving_node_ptr //
|| impl::is_native<unwrapped_type> //
@ -7337,7 +7366,7 @@ TOML_NAMESPACE_START
}
TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
typename ValueType,
typename ValueType = void,
typename KeyType,
typename... ValueArgs)
std::pair<iterator, bool> emplace(KeyType&& key, ValueArgs&&... args)
@ -7347,18 +7376,21 @@ TOML_NAMESPACE_START
"TOML_ENABLE_WINDOWS_COMPAT enabled.");
static_assert(!impl::is_cvref<ValueType>, "ValueType may not be const, volatile, or a reference.");
using value_type =
std::conditional_t<std::is_void_v<ValueType>, impl::emplaced_type_of<ValueArgs&&...>, ValueType>;
if constexpr (impl::is_wide_string<KeyType>)
{
#if TOML_ENABLE_WINDOWS_COMPAT
return emplace<ValueType>(impl::narrow(static_cast<KeyType&&>(key)), static_cast<ValueArgs&&>(args)...);
return emplace<value_type>(impl::narrow(static_cast<KeyType&&>(key)),
static_cast<ValueArgs&&>(args)...);
#else
static_assert(impl::dependent_false<KeyType>, "Evaluated unreachable branch!");
#endif
}
else
{
using unwrapped_type = impl::unwrap_node<ValueType>;
using unwrapped_type = impl::unwrap_node<value_type>;
static_assert((impl::is_native<unwrapped_type> || impl::is_one_of<unwrapped_type, table, array>),
"ValueType argument of table::emplace() must be one "
"of:" TOML_SA_UNWRAPPED_NODE_TYPE_LIST);

View File

@ -10,7 +10,7 @@ from pathlib import Path
def main():
hpp_path = Path(utils.entry_script_dir(), '..', 'toml.hpp').resolve()
hpp_path = Path(Path(__file__).resolve().parents[1], 'toml.hpp').resolve()
hash1 = utils.sha1(utils.read_all_text_from_file(hpp_path, logger=True))
print(rf'Hash 1: {hash1}')
utils.run_python_script(r'generate_single_header.py')

View File

@ -1,4 +1,4 @@
misk>=0.5.0
poxy>=0.5.2
misk>=0.6.0
poxy>=0.5.5
pyyaml
python-dateutil