diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5a9a0b0..2a20744 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: # g++-4.8 and 4.9 are tested on Travis.CI. - compiler: ['g++-9', 'g++-8', 'g++-7', 'g++-6', 'g++-5'] + compiler: ['g++-11', 'g++-10', 'g++-9', 'g++-8', 'g++-7', 'g++-6', 'g++-5'] standard: ['11', '14', '17', '20'] exclude: - {compiler: 'g++-5', standard: '17'} @@ -58,6 +58,8 @@ jobs: - {compiler: '5.0', standard: '20'} - {compiler: '6.0', standard: '20'} - {compiler: '7', standard: '20'} + - {compiler: '8', standard: '20'} + - {compiler: '9', standard: '20'} steps: - name: Checkout uses: actions/checkout@v2 diff --git a/README.md b/README.md index d5bc1c8..5f5040f 100644 --- a/README.md +++ b/README.md @@ -1255,8 +1255,16 @@ struct from In this way, since the conversion function is defined outside of the class, you can add conversion between `toml::value` and classes defined in another library. -Note that you cannot implement both of the functions because the overload -resolution of `toml::get` will be ambiguous. +In some cases, a class has a templatized constructor that takes a template, `T`. +It confuses `toml::get/find` because it makes the class "constructible" from +`toml::value`. To avoid this problem, `toml::from` and `from_toml` always +precede constructor. It makes easier to implement conversion between +`toml::value` and types defined in other libraries because it skips constructor. + +But, importantly, you cannot define `toml::from` and `T.from_toml` at the same +time because it causes ambiguity in the overload resolution of `toml::get` and `toml::find`. + +So the precedence is `toml::from` == `T.from_toml()` > `T(toml::value)`. If you want to convert any versions of `toml::basic_value`, you need to templatize the conversion function as follows. diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a19c9b0..031bdac 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -59,6 +59,7 @@ CHECK_CXX_COMPILER_FLAG("-Wuseless-cast" COMPILER_SUPPORTS_WUSELESS_CAST) CHECK_CXX_COMPILER_FLAG("-Wdouble-promotion" COMPILER_SUPPORTS_WDOUBLE_PROMOTION) CHECK_CXX_COMPILER_FLAG("-Wrange-loop-analysis" COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS) CHECK_CXX_COMPILER_FLAG("-Wundef" COMPILER_SUPPORTS_WUNDEF) +CHECK_CXX_COMPILER_FLAG("-Wshadow" COMPILER_SUPPORTS_WSHADOW) if(COMPILER_SUPPORTS_WALL) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") @@ -72,6 +73,9 @@ endif() if(COMPILER_SUPPORTS_WERROR) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") endif() +if(COMPILER_SUPPORTS_WSHADOW) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow") +endif() if(COMPILER_SUPPORTS_WSIGN_CONVERSION) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsign-conversion") endif() diff --git a/tests/test_comments.cpp b/tests/test_comments.cpp index 7438cae..635783a 100644 --- a/tests/test_comments.cpp +++ b/tests/test_comments.cpp @@ -190,7 +190,7 @@ BOOST_AUTO_TEST_CASE(test_discard_comment) )"; std::istringstream iss(file); - const auto v = toml::parse(iss); + const auto v = toml::parse(iss); const auto& a = toml::find(v, "a"); const auto& b = toml::find(v, "b"); diff --git a/tests/test_find.cpp b/tests/test_find.cpp index 5582da8..238390c 100644 --- a/tests/test_find.cpp +++ b/tests/test_find.cpp @@ -19,7 +19,7 @@ #include using test_value_types = std::tuple< - toml::value, + toml::basic_value, toml::basic_value, toml::basic_value, toml::basic_value diff --git a/tests/test_find_or.cpp b/tests/test_find_or.cpp index 434f943..72e5450 100644 --- a/tests/test_find_or.cpp +++ b/tests/test_find_or.cpp @@ -17,7 +17,7 @@ #endif using test_value_types = std::tuple< - toml::value, + toml::basic_value, toml::basic_value, toml::basic_value, toml::basic_value diff --git a/tests/test_get.cpp b/tests/test_get.cpp index 0749fd4..9a795f2 100644 --- a/tests/test_get.cpp +++ b/tests/test_get.cpp @@ -17,7 +17,7 @@ #endif using test_value_types = std::tuple< - toml::value, + toml::basic_value, toml::basic_value, toml::basic_value, toml::basic_value diff --git a/tests/test_get_or.cpp b/tests/test_get_or.cpp index 82e4839..a709ae7 100644 --- a/tests/test_get_or.cpp +++ b/tests/test_get_or.cpp @@ -17,7 +17,7 @@ #endif using test_value_types = std::tuple< - toml::value, + toml::basic_value, toml::basic_value, toml::basic_value, toml::basic_value diff --git a/tests/test_parse_array.cpp b/tests/test_parse_array.cpp index 2723b89..a75a6f1 100644 --- a/tests/test_parse_array.cpp +++ b/tests/test_parse_array.cpp @@ -71,62 +71,153 @@ BOOST_AUTO_TEST_CASE(test_oneline_array_value) BOOST_AUTO_TEST_CASE(test_multiline_array) { - TOML11_TEST_PARSE_EQUAL(parse_array, "[\n#comment\n]", array()); + TOML11_TEST_PARSE_EQUAL(parse_array>, "[\n#comment\n]", typename basic_value< discard_comments>::array_type()); + TOML11_TEST_PARSE_EQUAL(parse_array>, "[\n#comment\n]", typename basic_value::array_type()); + { - array a(5); - a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); - a[3] = toml::value(1); a[4] = toml::value(5); - TOML11_TEST_PARSE_EQUAL(parse_array, "[3,\n1,\n4,\n1,\n5]", a); + typename basic_value::array_type a(5); + a[0] = basic_value(3); + a[1] = basic_value(1); + a[2] = basic_value(4); + a[3] = basic_value(1); + a[4] = basic_value(5); + TOML11_TEST_PARSE_EQUAL(parse_array>, "[3,\n1,\n4,\n1,\n5]", a); } { - array a(3); - a[0] = toml::value("foo"); a[1] = toml::value("bar"); - a[2] = toml::value("baz"); - TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\",\n\"bar\",\n\"baz\"]", a); + typename basic_value::array_type a(5); + a[0] = basic_value(3); + a[1] = basic_value(1); + a[2] = basic_value(4); + a[3] = basic_value(1); + a[4] = basic_value(5); + TOML11_TEST_PARSE_EQUAL(parse_array>, "[3,\n1,\n4,\n1,\n5]", a); } { - array a(5); - a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); - a[3] = toml::value(1); a[4] = toml::value(5); - TOML11_TEST_PARSE_EQUAL(parse_array, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5]", a); + typename basic_value::array_type a(5); + a[0] = basic_value(3); + a[1] = basic_value(1); + a[2] = basic_value(4); + a[3] = basic_value(1); + a[4] = basic_value(5); + TOML11_TEST_PARSE_EQUAL(parse_array>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5 #comment\n]", a); } { - array a(3); - a[0] = toml::value("foo"); a[1] = toml::value("b#r"); - a[2] = toml::value("b#z"); - TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", a); + typename basic_value::array_type a(5); + a[0] = basic_value(3, {"comment"}); + a[1] = basic_value(1, {"comment"}); + a[2] = basic_value(4, {"comment"}); + a[3] = basic_value(1, {"comment"}); + a[4] = basic_value(5, {"comment"}); + TOML11_TEST_PARSE_EQUAL(parse_array>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5 #comment\n]", a); + } + + + { + typename basic_value::array_type a(3); + a[0] = basic_value("foo"); + a[1] = basic_value("bar"); + a[2] = basic_value("baz"); + TOML11_TEST_PARSE_EQUAL(parse_array>, "[\"foo\",\n\"bar\",\n\"baz\"]", a); + } + { + typename basic_value::array_type a(3); + a[0] = basic_value("foo"); + a[1] = basic_value("bar"); + a[2] = basic_value("baz"); + TOML11_TEST_PARSE_EQUAL(parse_array>, "[\"foo\",\n\"bar\",\n\"baz\"]", a); + } + + { + typename basic_value::array_type a(3); + a[0] = basic_value("foo"); + a[1] = basic_value("b#r"); + a[2] = basic_value("b#z"); + TOML11_TEST_PARSE_EQUAL(parse_array>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", a); + } + { + typename basic_value::array_type a(3); + a[0] = basic_value("foo", {"comment"}); + a[1] = basic_value("b#r", {"comment"}); + a[2] = basic_value("b#z", {"comment"}); + TOML11_TEST_PARSE_EQUAL(parse_array>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", a); } } BOOST_AUTO_TEST_CASE(test_multiline_array_value) { - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\n#comment\n]", toml::value(array())); + TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[\n#comment\n]", basic_value< discard_comments>(typename basic_value< discard_comments>::array_type())); + TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[\n#comment\n]", basic_value(typename basic_value::array_type())); + { - array a(5); - a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); - a[3] = toml::value(1); a[4] = toml::value(5); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[3,\n1,\n4,\n1,\n5]", toml::value(a)); + typename basic_value::array_type a(5); + a[0] = basic_value(3); + a[1] = basic_value(1); + a[2] = basic_value(4); + a[3] = basic_value(1); + a[4] = basic_value(5); + TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[3,\n1,\n4,\n1,\n5]", basic_value(a)); } { - array a(3); - a[0] = toml::value("foo"); a[1] = toml::value("bar"); - a[2] = toml::value("baz"); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\",\n\"bar\",\n\"baz\"]", toml::value(a)); + typename basic_value::array_type a(5); + a[0] = basic_value(3); + a[1] = basic_value(1); + a[2] = basic_value(4); + a[3] = basic_value(1); + a[4] = basic_value(5); + TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[3,\n1,\n4,\n1,\n5]", basic_value(a)); } { - array a(5); - a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); - a[3] = toml::value(1); a[4] = toml::value(5); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5]", toml::value(a)); + typename basic_value::array_type a(5); + a[0] = basic_value(3); + a[1] = basic_value(1); + a[2] = basic_value(4); + a[3] = basic_value(1); + a[4] = basic_value(5); + TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5 #comment\n]", basic_value(a)); } { - array a(3); - a[0] = toml::value("foo"); a[1] = toml::value("b#r"); - a[2] = toml::value("b#z"); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", toml::value(a)); + typename basic_value::array_type a(5); + a[0] = basic_value(3, {"comment"}); + a[1] = basic_value(1, {"comment"}); + a[2] = basic_value(4, {"comment"}); + a[3] = basic_value(1, {"comment"}); + a[4] = basic_value(5, {"comment"}); + TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5 #comment\n]", basic_value(a)); } + + + { + typename basic_value::array_type a(3); + a[0] = basic_value("foo"); + a[1] = basic_value("bar"); + a[2] = basic_value("baz"); + TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[\"foo\",\n\"bar\",\n\"baz\"]", basic_value(a)); + } + { + typename basic_value::array_type a(3); + a[0] = basic_value("foo"); + a[1] = basic_value("bar"); + a[2] = basic_value("baz"); + TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[\"foo\",\n\"bar\",\n\"baz\"]", basic_value(a)); + } + + { + typename basic_value::array_type a(3); + a[0] = basic_value("foo"); + a[1] = basic_value("b#r"); + a[2] = basic_value("b#z"); + TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", basic_value(a)); + } + { + typename basic_value::array_type a(3); + a[0] = basic_value("foo", {"comment"}); + a[1] = basic_value("b#r", {"comment"}); + a[2] = basic_value("b#z", {"comment"}); + TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", basic_value(a)); + } + } BOOST_AUTO_TEST_CASE(test_heterogeneous_array) @@ -176,14 +267,27 @@ BOOST_AUTO_TEST_CASE(test_heterogeneous_array) BOOST_AUTO_TEST_CASE(test_comments_after_comma) { { - array a; - a.push_back("foo"); - a.push_back("bar"); - a.push_back("baz"); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, + typename basic_value::array_type a(3); + a[0] = basic_value("foo"); + a[1] = basic_value("bar"); + a[2] = basic_value("baz"); + TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[ \"foo\" # comment\n" ", \"bar\" # comment\n" ", \"baz\" # comment\n" - "]", toml::value(a)); + "]", basic_value(a)); } + + { + typename basic_value::array_type a(3); + a[0] = basic_value("foo", {" comment"}); + a[1] = basic_value("bar", {" comment"}); + a[2] = basic_value("baz", {" comment"}); + TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, + "[ \"foo\" # comment\n" + ", \"bar\" # comment\n" + ", \"baz\" # comment\n" + "]", basic_value(a)); + } + } diff --git a/tests/test_serialize_file.cpp b/tests/test_serialize_file.cpp index b5c408e..7e1d8e1 100644 --- a/tests/test_serialize_file.cpp +++ b/tests/test_serialize_file.cpp @@ -127,8 +127,8 @@ BOOST_AUTO_TEST_CASE(test_example_with_comment_nocomment) BOOST_TEST(!has_comment_inside(serialized)); } { - const auto data_nocomment = toml::parse("toml/tests/example.toml"); - auto serialized = toml::parse("tmp1_com_nocomment.toml"); + const auto data_nocomment = toml::parse("toml/tests/example.toml"); + auto serialized = toml::parse("tmp1_com_nocomment.toml"); { auto& owner = toml::find(serialized, "owner"); auto& bio = toml::find(owner, "bio"); @@ -182,8 +182,8 @@ BOOST_AUTO_TEST_CASE(test_example_with_comment_map_dq_nocomment) BOOST_TEST(!has_comment_inside(serialized)); } { - const auto data_nocomment = toml::parse("toml/tests/example.toml"); - auto serialized = toml::parse("tmp1_com_map_dq_nocomment.toml"); + const auto data_nocomment = toml::parse("toml/tests/example.toml"); + auto serialized = toml::parse("tmp1_com_map_dq_nocomment.toml"); { auto& owner = toml::find(serialized, "owner"); auto& bio = toml::find(owner, "bio"); diff --git a/toml/comments.hpp b/toml/comments.hpp index 92fc8e1..b9ce806 100644 --- a/toml/comments.hpp +++ b/toml/comments.hpp @@ -10,6 +10,12 @@ #include #include +#ifdef TOML11_PRESERVE_COMMENTS_BY_DEFAULT +# define TOML11_DEFAULT_COMMENT_STRATEGY ::toml::preserve_comments +#else +# define TOML11_DEFAULT_COMMENT_STRATEGY ::toml::discard_comments +#endif + // This file provides mainly two classes, `preserve_comments` and `discard_comments`. // Those two are a container that have the same interface as `std::vector` // but bahaves in the opposite way. `preserve_comments` is just the same as diff --git a/toml/get.hpp b/toml/get.hpp index 0f9aeab..f462368 100644 --- a/toml/get.hpp +++ b/toml/get.hpp @@ -255,16 +255,19 @@ get(const basic_value&); // toml::from::from_toml(v) template class M, template class V, - std::size_t S = sizeof(::toml::from)> -T get(const basic_value&); + template class M, template class V> +detail::enable_if_t::value, T> +get(const basic_value&); -// T(const toml::value&) and T is not toml::basic_value +// T(const toml::value&) and T is not toml::basic_value, +// and it does not have `from` nor `from_toml`. template class M, template class V> detail::enable_if_t>, - std::is_constructible&> + std::is_constructible&>, + detail::negation>, + detail::negation> >::value, T> get(const basic_value&); @@ -440,9 +443,9 @@ get(const basic_value& v) return ud; } template class M, template class V, - std::size_t> -T get(const basic_value& v) + template class M, template class V> +detail::enable_if_t::value, T> +get(const basic_value& v) { return ::toml::from::from_toml(v); } @@ -450,8 +453,10 @@ T get(const basic_value& v) template class M, template class V> detail::enable_if_t>, - std::is_constructible&> + detail::negation>, // T is not a toml::value + std::is_constructible&>, // T is constructible from toml::value + detail::negation>, // and T does not have T.from_toml(v); + detail::negation> // and T does not have toml::from{}; >::value, T> get(const basic_value& v) { diff --git a/toml/literal.hpp b/toml/literal.hpp index 0824f83..1d338b7 100644 --- a/toml/literal.hpp +++ b/toml/literal.hpp @@ -12,11 +12,11 @@ inline namespace toml_literals { // implementation -inline ::toml::basic_value<::toml::discard_comments, std::unordered_map, std::vector> +inline ::toml::basic_value literal_internal_impl(::toml::detail::location loc) { using value_type = ::toml::basic_value< - ::toml::discard_comments, std::unordered_map, std::vector>; + TOML11_DEFAULT_COMMENT_STRATEGY, std::unordered_map, std::vector>; // if there are some comments or empty lines, skip them. using skip_line = ::toml::detail::repeat, @@ -81,7 +81,7 @@ literal_internal_impl(::toml::detail::location loc) } -inline ::toml::basic_value<::toml::discard_comments, std::unordered_map, std::vector> +inline ::toml::basic_value operator"" _toml(const char* str, std::size_t len) { ::toml::detail::location loc( @@ -95,7 +95,7 @@ operator"" _toml(const char* str, std::size_t len) #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L // value of u8"" literal has been changed from char to char8_t and char8_t is // NOT compatible to char -inline ::toml::basic_value<::toml::discard_comments, std::unordered_map, std::vector> +inline ::toml::basic_value operator"" _toml(const char8_t* str, std::size_t len) { ::toml::detail::location loc( diff --git a/toml/parser.hpp b/toml/parser.hpp index c3df644..231df80 100644 --- a/toml/parser.hpp +++ b/toml/parser.hpp @@ -2076,7 +2076,7 @@ result parse_toml_file(location& loc) } // detail -template class Table = std::unordered_map, template class Array = std::vector> basic_value @@ -2127,7 +2127,7 @@ parse(std::istream& is, const std::string& fname = "unknown file") return data.unwrap(); } -template class Table = std::unordered_map, template class Array = std::vector> basic_value parse(const std::string& fname) @@ -2150,7 +2150,7 @@ basic_value parse(const std::string& fname) // // This function exactly matches to the invokation with c-string. // So this function is preferred than others and the ambiguity disappears. -template class Table = std::unordered_map, template class Array = std::vector> basic_value parse(const char* fname) @@ -2158,7 +2158,7 @@ basic_value parse(const char* fname) return parse(std::string(fname)); } -template class Table = std::unordered_map, template class Array = std::vector> basic_value parse(const std::filesystem::path& fpath) diff --git a/toml/region.hpp b/toml/region.hpp index 37ba3a3..2e01e51 100644 --- a/toml/region.hpp +++ b/toml/region.hpp @@ -73,13 +73,13 @@ struct location final : public region_base using difference_type = typename const_iterator::difference_type; using source_ptr = std::shared_ptr>; - location(std::string name, std::vector cont) + location(std::string source_name, std::vector cont) : source_(std::make_shared>(std::move(cont))), - line_number_(1), source_name_(std::move(name)), iter_(source_->cbegin()) + line_number_(1), source_name_(std::move(source_name)), iter_(source_->cbegin()) {} - location(std::string name, const std::string& cont) + location(std::string source_name, const std::string& cont) : source_(std::make_shared>(cont.begin(), cont.end())), - line_number_(1), source_name_(std::move(name)), iter_(source_->cbegin()) + line_number_(1), source_name_(std::move(source_name)), iter_(source_->cbegin()) {} location(const location&) = default; @@ -343,9 +343,9 @@ struct region final : public region_base })) { // unwrap the first '#' by std::next. - auto str = make_string(std::next(comment_found), iter); - if(!str.empty() && str.back() == '\r') {str.pop_back();} - com.push_back(std::move(str)); + auto s = make_string(std::next(comment_found), iter); + if(!s.empty() && s.back() == '\r') {s.pop_back();} + com.push_back(std::move(s)); } else { @@ -396,9 +396,9 @@ struct region final : public region_base })) { // unwrap the first '#' by std::next. - auto str = make_string(std::next(comment_found), this->line_end()); - if(!str.empty() && str.back() == '\r') {str.pop_back();} - com.push_back(std::move(str)); + auto s = make_string(std::next(comment_found), this->line_end()); + if(!s.empty() && s.back() == '\r') {s.pop_back();} + com.push_back(std::move(s)); } } } diff --git a/toml/serializer.hpp b/toml/serializer.hpp index 77aef58..b27abfd 100644 --- a/toml/serializer.hpp +++ b/toml/serializer.hpp @@ -26,19 +26,19 @@ namespace toml // a `"` and escaping some special character is boring. template std::basic_string -format_key(const std::basic_string& key) +format_key(const std::basic_string& k) { // check the key can be a bare (unquoted) key - detail::location loc(key, std::vector(key.begin(), key.end())); + detail::location loc(k, std::vector(k.begin(), k.end())); detail::lex_unquoted_key::invoke(loc); if(loc.iter() == loc.end()) { - return key; // all the tokens are consumed. the key is unquoted-key. + return k; // all the tokens are consumed. the key is unquoted-key. } //if it includes special characters, then format it in a "quoted" key. std::basic_string serialized("\""); - for(const char c : key) + for(const char c : k) { switch(c) { diff --git a/toml/traits.hpp b/toml/traits.hpp index eafa6af..0064e37 100644 --- a/toml/traits.hpp +++ b/toml/traits.hpp @@ -2,6 +2,10 @@ // Distributed under the MIT License. #ifndef TOML11_TRAITS_HPP #define TOML11_TRAITS_HPP + +#include "from.hpp" +#include "into.hpp" + #include #include #include @@ -84,6 +88,22 @@ struct has_into_toml_method_impl static std::false_type check(...); }; +struct has_specialized_from_impl +{ + template + static std::false_type check(...); + template)> + static std::true_type check(::toml::from*); +}; +struct has_specialized_into_impl +{ + template + static std::false_type check(...); + template)> + static std::true_type check(::toml::from*); +}; + + /// Intel C++ compiler can not use decltype in parent class declaration, here /// is a hack to work around it. https://stackoverflow.com/a/23953090/4692076 #ifdef __INTEL_COMPILER @@ -114,6 +134,11 @@ template struct has_into_toml_method : decltype(has_into_toml_method_impl::check(nullptr)){}; +template +struct has_specialized_from : decltype(has_specialized_from_impl::check(nullptr)){}; +template +struct has_specialized_into : decltype(has_specialized_into_impl::check(nullptr)){}; + #ifdef __INTEL_COMPILER #undef decltype #endif diff --git a/toml/types.hpp b/toml/types.hpp index 0818ebd..7bf4b2e 100644 --- a/toml/types.hpp +++ b/toml/types.hpp @@ -21,6 +21,11 @@ class basic_value; using character = char; using key = std::string; +#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ <= 4 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wshadow" +#endif + using boolean = bool; using integer = std::int64_t; using floating = double; // "float" is a keyward, cannot use it here. @@ -32,12 +37,26 @@ using floating = double; // "float" is a keyward, cannot use it here. // - local_date // - local_time +#if defined(__GNUC__) && !defined(__clang__) +# pragma GCC diagnostic pop +#endif + // default toml::value and default array/table. these are defined after defining // basic_value itself. // using value = basic_value; // using array = typename value::array_type; // using table = typename value::table_type; +// to avoid warnings about `value_t::integer` is "shadowing" toml::integer in +// GCC -Wshadow=global. +#if defined(__GNUC__) && !defined(__clang__) +# pragma GCC diagnostic push +# if 7 <= __GNUC__ +# pragma GCC diagnostic ignored "-Wshadow=global" +# else // gcc-6 or older +# pragma GCC diagnostic ignored "-Wshadow" +# endif +#endif enum class value_t : std::uint8_t { empty = 0, @@ -52,6 +71,9 @@ enum class value_t : std::uint8_t array = 9, table = 10, }; +#if defined(__GNUC__) && !defined(__clang__) +# pragma GCC diagnostic pop +#endif template inline std::basic_ostream& @@ -147,4 +169,5 @@ template struct is_exact_toml_type } // detail } // toml + #endif// TOML11_TYPES_H diff --git a/toml/value.hpp b/toml/value.hpp index e374c3b..ed8c76e 100644 --- a/toml/value.hpp +++ b/toml/value.hpp @@ -281,9 +281,9 @@ class basic_value // overwrite comments ---------------------------------------------------- - basic_value(const basic_value& v, std::vector comments) + basic_value(const basic_value& v, std::vector com) : type_(v.type()), region_info_(v.region_info_), - comments_(std::move(comments)) + comments_(std::move(com)) { switch(v.type()) { @@ -301,9 +301,9 @@ class basic_value } } - basic_value(basic_value&& v, std::vector comments) + basic_value(basic_value&& v, std::vector com) : type_(v.type()), region_info_(std::move(v.region_info_)), - comments_(std::move(comments)) + comments_(std::move(com)) { switch(this->type_) // here this->type_ is already initialized { @@ -359,9 +359,9 @@ class basic_value template class T, template class A> - basic_value(const basic_value& v, std::vector comments) + basic_value(const basic_value& v, std::vector com) : type_(v.type()), region_info_(v.region_info_), - comments_(std::move(comments)) + comments_(std::move(com)) { switch(v.type()) { @@ -443,10 +443,10 @@ class basic_value assigner(this->boolean_, b); return *this; } - basic_value(boolean b, std::vector comments) + basic_value(boolean b, std::vector com) : type_(value_t::boolean), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { assigner(this->boolean_, b); } @@ -478,10 +478,10 @@ class basic_value template, detail::negation>>::value, std::nullptr_t>::type = nullptr> - basic_value(T i, std::vector comments) + basic_value(T i, std::vector com) : type_(value_t::integer), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { assigner(this->integer_, static_cast(i)); } @@ -511,10 +511,10 @@ class basic_value template::value, std::nullptr_t>::type = nullptr> - basic_value(T f, std::vector comments) + basic_value(T f, std::vector com) : type_(value_t::floating), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { assigner(this->floating_, f); } @@ -535,10 +535,10 @@ class basic_value assigner(this->string_, s); return *this; } - basic_value(toml::string s, std::vector comments) + basic_value(toml::string s, std::vector com) : type_(value_t::string), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { assigner(this->string_, std::move(s)); } @@ -563,17 +563,17 @@ class basic_value { assigner(this->string_, toml::string(std::move(s), kind)); } - basic_value(std::string s, std::vector comments) + basic_value(std::string s, std::vector com) : type_(value_t::string), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { assigner(this->string_, toml::string(std::move(s))); } - basic_value(std::string s, string_t kind, std::vector comments) + basic_value(std::string s, string_t kind, std::vector com) : type_(value_t::string), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { assigner(this->string_, toml::string(std::move(s), kind)); } @@ -598,17 +598,17 @@ class basic_value { assigner(this->string_, toml::string(std::string(s), kind)); } - basic_value(const char* s, std::vector comments) + basic_value(const char* s, std::vector com) : type_(value_t::string), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { assigner(this->string_, toml::string(std::string(s))); } - basic_value(const char* s, string_t kind, std::vector comments) + basic_value(const char* s, string_t kind, std::vector com) : type_(value_t::string), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { assigner(this->string_, toml::string(std::string(s), kind)); } @@ -628,10 +628,10 @@ class basic_value assigner(this->string_, toml::string(s)); return *this; } - basic_value(std::string_view s, std::vector comments) + basic_value(std::string_view s, std::vector com) : type_(value_t::string), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { assigner(this->string_, toml::string(s)); } @@ -641,10 +641,10 @@ class basic_value { assigner(this->string_, toml::string(s, kind)); } - basic_value(std::string_view s, string_t kind, std::vector comments) + basic_value(std::string_view s, string_t kind, std::vector com) : type_(value_t::string), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { assigner(this->string_, toml::string(s, kind)); } @@ -666,10 +666,10 @@ class basic_value assigner(this->local_date_, ld); return *this; } - basic_value(const local_date& ld, std::vector comments) + basic_value(const local_date& ld, std::vector com) : type_(value_t::local_date), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { assigner(this->local_date_, ld); } @@ -682,10 +682,10 @@ class basic_value { assigner(this->local_time_, lt); } - basic_value(const local_time& lt, std::vector comments) + basic_value(const local_time& lt, std::vector com) : type_(value_t::local_time), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { assigner(this->local_time_, lt); } @@ -707,10 +707,10 @@ class basic_value } template basic_value(const std::chrono::duration& dur, - std::vector comments) + std::vector com) : type_(value_t::local_time), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { assigner(this->local_time_, local_time(dur)); } @@ -732,10 +732,10 @@ class basic_value { assigner(this->local_datetime_, ldt); } - basic_value(const local_datetime& ldt, std::vector comments) + basic_value(const local_datetime& ldt, std::vector com) : type_(value_t::local_datetime), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { assigner(this->local_datetime_, ldt); } @@ -756,10 +756,10 @@ class basic_value { assigner(this->offset_datetime_, odt); } - basic_value(const offset_datetime& odt, std::vector comments) + basic_value(const offset_datetime& odt, std::vector com) : type_(value_t::offset_datetime), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { assigner(this->offset_datetime_, odt); } @@ -778,10 +778,10 @@ class basic_value assigner(this->offset_datetime_, offset_datetime(tp)); } basic_value(const std::chrono::system_clock::time_point& tp, - std::vector comments) + std::vector com) : type_(value_t::offset_datetime), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { assigner(this->offset_datetime_, offset_datetime(tp)); } @@ -802,10 +802,10 @@ class basic_value { assigner(this->array_, ary); } - basic_value(const array_type& ary, std::vector comments) + basic_value(const array_type& ary, std::vector com) : type_(value_t::array), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { assigner(this->array_, ary); } @@ -833,10 +833,10 @@ class basic_value template::value, std::nullptr_t>::type = nullptr> - basic_value(std::initializer_list list, std::vector comments) + basic_value(std::initializer_list list, std::vector com) : type_(value_t::array), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { array_type ary(list.begin(), list.end()); assigner(this->array_, std::move(ary)); @@ -876,10 +876,10 @@ class basic_value detail::negation>, detail::is_container >::value, std::nullptr_t>::type = nullptr> - basic_value(const T& list, std::vector comments) + basic_value(const T& list, std::vector com) : type_(value_t::array), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { static_assert(std::is_convertible::value, "elements of a container should be convertible to toml::value"); @@ -915,10 +915,10 @@ class basic_value { assigner(this->table_, tab); } - basic_value(const table_type& tab, std::vector comments) + basic_value(const table_type& tab, std::vector com) : type_(value_t::table), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { assigner(this->table_, tab); } @@ -943,10 +943,10 @@ class basic_value } basic_value(std::initializer_list> list, - std::vector comments) + std::vector com) : type_(value_t::table), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { table_type tab; for(const auto& elem : list) {tab[elem.first] = elem.second;} @@ -982,10 +982,10 @@ class basic_value detail::negation>, detail::is_map >::value, std::nullptr_t>::type = nullptr> - basic_value(const Map& mp, std::vector comments) + basic_value(const Map& mp, std::vector com) : type_(value_t::table), region_info_(std::make_shared(region_base{})), - comments_(std::move(comments)) + comments_(std::move(com)) { table_type tab; for(const auto& elem : mp) {tab[elem.first] = elem.second;} @@ -1017,8 +1017,8 @@ class basic_value template::value, std::nullptr_t>::type = nullptr> - basic_value(const T& ud, std::vector comments) - : basic_value(ud.into_toml(), std::move(comments)) + basic_value(const T& ud, std::vector com) + : basic_value(ud.into_toml(), std::move(com)) {} template::value, std::nullptr_t>::type = nullptr> @@ -1033,8 +1033,8 @@ class basic_value template)> basic_value(const T& ud): basic_value(::toml::into::into_toml(ud)) {} template)> - basic_value(const T& ud, std::vector comments) - : basic_value(::toml::into::into_toml(ud), std::move(comments)) + basic_value(const T& ud, std::vector com) + : basic_value(::toml::into::into_toml(ud), std::move(com)) {} template)> basic_value& operator=(const T& ud) @@ -1134,10 +1134,10 @@ class basic_value template::value, std::nullptr_t>::type = nullptr> - basic_value(std::pair parse_result, std::vector comments) + basic_value(std::pair parse_result, std::vector com) : basic_value(std::move(parse_result.first), std::move(parse_result.second), - std::move(comments)) + std::move(com)) {} // type checking and casting ============================================ @@ -1739,7 +1739,8 @@ class basic_value }; // default toml::value and default array/table. -using value = basic_value; +// TOML11_DEFAULT_COMMENT_STRATEGY is defined in comments.hpp +using value = basic_value; using array = typename value::array_type; using table = typename value::table_type;