Skip to content

Commit

Permalink
fix(#279): fix compilation with older msvc
Browse files Browse the repository at this point in the history
by avoiding known SFINAE problem in msvc 2017
  • Loading branch information
ToruNiina committed Jan 12, 2025
1 parent c9a00de commit 844e8fd
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 67 deletions.
33 changes: 23 additions & 10 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,40 @@ version: "{build}"

environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
MSVC_VERSION: 2017
CXX_VERSION: 11
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
MSVC_VERSION: 2017
CXX_VERSION: 14
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
MSVC_VERSION: 2017
CXX_VERSION: 17
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
generator: Visual Studio 16 2019
systemver: 10.0.18362.0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
generator: Visual Studio 17 2022
systemver: 10.0.22621.0
MSVC_VERSION: 2019
CXX_VERSION: 11
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
MSVC_VERSION: 2019
CXX_VERSION: 14
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
MSVC_VERSION: 2019
CXX_VERSION: 17

configuration:
- Release
- Debug

clone_depth: 10
clone_folder: c:\toml11

install:
- git submodule update --init --recursive
- git submodule update --init --recursive

build_script:
- '"C:\Program Files (x86)\Microsoft Visual Studio\%MSVC_VERSION%\Community\VC\Auxiliary\Build\vcvarsall.bat" x64'
- cd C:\toml11
- cmake -B build -G"%generator%" -DCMAKE_SYSTEM_VERSION="%systemver%" -A x64 -DCMAKE_CXX_STANDARD=11 -DTOML11_BUILD_TESTS=ON -DTOML11_PRECOMPILE=ON
- cmake --build build --config "%configuration%"
- cmake -B build -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=%configuration% -DCMAKE_CXX_STANDARD=%CXX_VERSION% -DTOML11_BUILD_TESTS=ON -DBUILD_TESTING=ON -DTOML11_PRECOMPILE=ON
- cmake --build build

test_script:
- ctest --test-dir build --build-config "%configuration%" --timeout 300 --output-on-failure
- cd build\tests\
- ctest --timeout 300 --output-on-failure
29 changes: 29 additions & 0 deletions include/toml11/compat.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,35 @@ using return_type_of_t = typename std::result_of<F(Args...)>::type;
} // cxx
} // toml

// ---------------------------------------------------------------------------
// C++17 void_t

#if TOML11_CPLUSPLUS_STANDARD_VERSION >= TOML11_CXX17_VALUE
# if defined(__cpp_lib_void_t)
# if __cpp_lib_void_t >= 201411L
# define TOML11_HAS_STD_VOID_T 1
# endif
# endif
#endif

namespace toml
{
namespace cxx
{
#if defined(TOML11_HAS_STD_VOID_T)

using std::void_t;

#else

template<typename ...>
using void_t = void;

#endif // TOML11_HAS_STD_VOID_T

} // cxx
} // toml

// ----------------------------------------------------------------------------
// (subset of) source_location

Expand Down
91 changes: 34 additions & 57 deletions include/toml11/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define TOML11_TYPES_HPP

#include "comments.hpp"
#include "compat.hpp"
#include "error_info.hpp"
#include "format.hpp"
#include "ordered_map.hpp"
Expand Down Expand Up @@ -299,77 +300,53 @@ namespace detail
// ----------------------------------------------------------------------------
// check if type T has all the needed member types

struct has_comment_type_impl
{
template<typename T> static std::true_type check(typename T::comment_type*);
template<typename T> static std::false_type check(...);
};
template<typename T, typename U = void>
struct has_comment_type: std::false_type{};
template<typename T>
using has_comment_type = decltype(has_comment_type_impl::check<T>(nullptr));
struct has_comment_type<T, cxx::void_t<typename T::comment_type>>: std::true_type{};

struct has_integer_type_impl
{
template<typename T> static std::true_type check(typename T::integer_type*);
template<typename T> static std::false_type check(...);
};
template<typename T, typename U = void>
struct has_integer_type: std::false_type{};
template<typename T>
using has_integer_type = decltype(has_integer_type_impl::check<T>(nullptr));
struct has_integer_type<T, cxx::void_t<typename T::integer_type>>: std::true_type{};

struct has_floating_type_impl
{
template<typename T> static std::true_type check(typename T::floating_type*);
template<typename T> static std::false_type check(...);
};
template<typename T, typename U = void>
struct has_floating_type: std::false_type{};
template<typename T>
using has_floating_type = decltype(has_floating_type_impl::check<T>(nullptr));
struct has_floating_type<T, cxx::void_t<typename T::floating_type>>: std::true_type{};

struct has_string_type_impl
{
template<typename T> static std::true_type check(typename T::string_type*);
template<typename T> static std::false_type check(...);
};
template<typename T, typename U = void>
struct has_string_type: std::false_type{};
template<typename T>
using has_string_type = decltype(has_string_type_impl::check<T>(nullptr));
struct has_string_type<T, cxx::void_t<typename T::string_type>>: std::true_type{};

struct has_array_type_impl
{
template<typename T> static std::true_type check(typename T::template array_type<int>*);
template<typename T> static std::false_type check(...);
};
template<typename T, typename U = void>
struct has_array_type: std::false_type{};
template<typename T>
using has_array_type = decltype(has_array_type_impl::check<T>(nullptr));
struct has_array_type<T, cxx::void_t<typename T::template array_type<int>>>: std::true_type{};

struct has_table_type_impl
{
template<typename T> static std::true_type check(typename T::template table_type<int, int>*);
template<typename T> static std::false_type check(...);
};
template<typename T, typename U = void>
struct has_table_type: std::false_type{};
template<typename T>
using has_table_type = decltype(has_table_type_impl::check<T>(nullptr));
struct has_table_type<T, cxx::void_t<typename T::template table_type<int, int>>>: std::true_type{};

struct has_parse_int_impl
{
template<typename T> static std::true_type check(decltype(std::declval<T>().parse_int(
std::declval<const std::string&>(),
std::declval<const source_location>(),
std::declval<const std::uint8_t>()
))*);
template<typename T> static std::false_type check(...);
};
template<typename T, typename U = void>
struct has_parse_int: std::false_type{};
template<typename T>
using has_parse_int = decltype(has_parse_int_impl::check<T>(nullptr));

struct has_parse_float_impl
{
template<typename T> static std::true_type check(decltype(std::declval<T>().parse_float(
std::declval<const std::string&>(),
std::declval<const source_location>(),
std::declval<const bool>()
))*);
template<typename T> static std::false_type check(...);
};
struct has_parse_int<T, cxx::void_t<decltype(std::declval<T>().parse_int(
std::declval<std::string const&>(),
std::declval<::toml::source_location const&>(),
std::declval<std::uint8_t>()
))>>: std::true_type{};

template<typename T, typename U = void>
struct has_parse_float: std::false_type{};
template<typename T>
using has_parse_float = decltype(has_parse_float_impl::check<T>(nullptr));
struct has_parse_float<T, cxx::void_t<decltype(std::declval<T>().parse_float(
std::declval<std::string const&>(),
std::declval<::toml::source_location const&>(),
std::declval<bool>()
))>>: std::true_type{};

template<typename T>
using is_type_config = cxx::conjunction<
Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ set(TOML11_TEST_NAMES
test_parse_inline_table
test_parse_table_keys
test_parse_table
test_parse
test_result
test_scanner
test_serialize
Expand Down
50 changes: 50 additions & 0 deletions tests/test_parse.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"

#include <toml.hpp>

#include <clocale>

TEST_CASE("testing toml::parse(file)")
{
using namespace toml::literals::toml_literals;

const std::string spec_example(R"(# This is a TOML document
title = "TOML Example"
[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00
[database]
enabled = true
ports = [ 8000, 8001, 8002 ]
data = [ ["delta", "phi"], [3.14] ]
temp_targets = { cpu = 79.5, case = 72.0 }
[servers]
[servers.alpha]
ip = "10.0.0.1"
role = "frontend"
[servers.beta]
ip = "10.0.0.2"
role = "backend"
)");

{
std::ofstream ofs("test_parse.toml");
ofs << spec_example;
}

const auto u = toml::parse_str(spec_example);
const auto v = toml::parse("test_parse.toml");

CHECK_EQ(u, v);

CHECK_EQ(toml::find<int>(v, "database", "ports", 0), 8000);
CHECK_EQ(toml::find<int>(v, "database", "ports", 1), 8001);
CHECK_EQ(toml::find<int>(v, "database", "ports", 2), 8002);
}

0 comments on commit 844e8fd

Please sign in to comment.