Skip to content

Commit 844e8fd

Browse files
committed
fix(#279): fix compilation with older msvc
by avoiding known SFINAE problem in msvc 2017
1 parent c9a00de commit 844e8fd

File tree

5 files changed

+137
-67
lines changed

5 files changed

+137
-67
lines changed

appveyor.yml

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,40 @@ version: "{build}"
22

33
environment:
44
matrix:
5+
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
6+
MSVC_VERSION: 2017
7+
CXX_VERSION: 11
8+
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
9+
MSVC_VERSION: 2017
10+
CXX_VERSION: 14
11+
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
12+
MSVC_VERSION: 2017
13+
CXX_VERSION: 17
514
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
6-
generator: Visual Studio 16 2019
7-
systemver: 10.0.18362.0
8-
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
9-
generator: Visual Studio 17 2022
10-
systemver: 10.0.22621.0
15+
MSVC_VERSION: 2019
16+
CXX_VERSION: 11
17+
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
18+
MSVC_VERSION: 2019
19+
CXX_VERSION: 14
20+
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
21+
MSVC_VERSION: 2019
22+
CXX_VERSION: 17
1123

1224
configuration:
13-
- Release
1425
- Debug
1526

1627
clone_depth: 10
1728
clone_folder: c:\toml11
1829

1930
install:
20-
- git submodule update --init --recursive
31+
- git submodule update --init --recursive
2132

2233
build_script:
34+
- '"C:\Program Files (x86)\Microsoft Visual Studio\%MSVC_VERSION%\Community\VC\Auxiliary\Build\vcvarsall.bat" x64'
2335
- cd C:\toml11
24-
- cmake -B build -G"%generator%" -DCMAKE_SYSTEM_VERSION="%systemver%" -A x64 -DCMAKE_CXX_STANDARD=11 -DTOML11_BUILD_TESTS=ON -DTOML11_PRECOMPILE=ON
25-
- cmake --build build --config "%configuration%"
36+
- 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
37+
- cmake --build build
2638

2739
test_script:
28-
- ctest --test-dir build --build-config "%configuration%" --timeout 300 --output-on-failure
40+
- cd build\tests\
41+
- ctest --timeout 300 --output-on-failure

include/toml11/compat.hpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,35 @@ using return_type_of_t = typename std::result_of<F(Args...)>::type;
386386
} // cxx
387387
} // toml
388388

389+
// ---------------------------------------------------------------------------
390+
// C++17 void_t
391+
392+
#if TOML11_CPLUSPLUS_STANDARD_VERSION >= TOML11_CXX17_VALUE
393+
# if defined(__cpp_lib_void_t)
394+
# if __cpp_lib_void_t >= 201411L
395+
# define TOML11_HAS_STD_VOID_T 1
396+
# endif
397+
# endif
398+
#endif
399+
400+
namespace toml
401+
{
402+
namespace cxx
403+
{
404+
#if defined(TOML11_HAS_STD_VOID_T)
405+
406+
using std::void_t;
407+
408+
#else
409+
410+
template<typename ...>
411+
using void_t = void;
412+
413+
#endif // TOML11_HAS_STD_VOID_T
414+
415+
} // cxx
416+
} // toml
417+
389418
// ----------------------------------------------------------------------------
390419
// (subset of) source_location
391420

include/toml11/types.hpp

Lines changed: 34 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define TOML11_TYPES_HPP
33

44
#include "comments.hpp"
5+
#include "compat.hpp"
56
#include "error_info.hpp"
67
#include "format.hpp"
78
#include "ordered_map.hpp"
@@ -299,77 +300,53 @@ namespace detail
299300
// ----------------------------------------------------------------------------
300301
// check if type T has all the needed member types
301302

302-
struct has_comment_type_impl
303-
{
304-
template<typename T> static std::true_type check(typename T::comment_type*);
305-
template<typename T> static std::false_type check(...);
306-
};
303+
template<typename T, typename U = void>
304+
struct has_comment_type: std::false_type{};
307305
template<typename T>
308-
using has_comment_type = decltype(has_comment_type_impl::check<T>(nullptr));
306+
struct has_comment_type<T, cxx::void_t<typename T::comment_type>>: std::true_type{};
309307

310-
struct has_integer_type_impl
311-
{
312-
template<typename T> static std::true_type check(typename T::integer_type*);
313-
template<typename T> static std::false_type check(...);
314-
};
308+
template<typename T, typename U = void>
309+
struct has_integer_type: std::false_type{};
315310
template<typename T>
316-
using has_integer_type = decltype(has_integer_type_impl::check<T>(nullptr));
311+
struct has_integer_type<T, cxx::void_t<typename T::integer_type>>: std::true_type{};
317312

318-
struct has_floating_type_impl
319-
{
320-
template<typename T> static std::true_type check(typename T::floating_type*);
321-
template<typename T> static std::false_type check(...);
322-
};
313+
template<typename T, typename U = void>
314+
struct has_floating_type: std::false_type{};
323315
template<typename T>
324-
using has_floating_type = decltype(has_floating_type_impl::check<T>(nullptr));
316+
struct has_floating_type<T, cxx::void_t<typename T::floating_type>>: std::true_type{};
325317

326-
struct has_string_type_impl
327-
{
328-
template<typename T> static std::true_type check(typename T::string_type*);
329-
template<typename T> static std::false_type check(...);
330-
};
318+
template<typename T, typename U = void>
319+
struct has_string_type: std::false_type{};
331320
template<typename T>
332-
using has_string_type = decltype(has_string_type_impl::check<T>(nullptr));
321+
struct has_string_type<T, cxx::void_t<typename T::string_type>>: std::true_type{};
333322

334-
struct has_array_type_impl
335-
{
336-
template<typename T> static std::true_type check(typename T::template array_type<int>*);
337-
template<typename T> static std::false_type check(...);
338-
};
323+
template<typename T, typename U = void>
324+
struct has_array_type: std::false_type{};
339325
template<typename T>
340-
using has_array_type = decltype(has_array_type_impl::check<T>(nullptr));
326+
struct has_array_type<T, cxx::void_t<typename T::template array_type<int>>>: std::true_type{};
341327

342-
struct has_table_type_impl
343-
{
344-
template<typename T> static std::true_type check(typename T::template table_type<int, int>*);
345-
template<typename T> static std::false_type check(...);
346-
};
328+
template<typename T, typename U = void>
329+
struct has_table_type: std::false_type{};
347330
template<typename T>
348-
using has_table_type = decltype(has_table_type_impl::check<T>(nullptr));
331+
struct has_table_type<T, cxx::void_t<typename T::template table_type<int, int>>>: std::true_type{};
349332

350-
struct has_parse_int_impl
351-
{
352-
template<typename T> static std::true_type check(decltype(std::declval<T>().parse_int(
353-
std::declval<const std::string&>(),
354-
std::declval<const source_location>(),
355-
std::declval<const std::uint8_t>()
356-
))*);
357-
template<typename T> static std::false_type check(...);
358-
};
333+
template<typename T, typename U = void>
334+
struct has_parse_int: std::false_type{};
359335
template<typename T>
360-
using has_parse_int = decltype(has_parse_int_impl::check<T>(nullptr));
361-
362-
struct has_parse_float_impl
363-
{
364-
template<typename T> static std::true_type check(decltype(std::declval<T>().parse_float(
365-
std::declval<const std::string&>(),
366-
std::declval<const source_location>(),
367-
std::declval<const bool>()
368-
))*);
369-
template<typename T> static std::false_type check(...);
370-
};
336+
struct has_parse_int<T, cxx::void_t<decltype(std::declval<T>().parse_int(
337+
std::declval<std::string const&>(),
338+
std::declval<::toml::source_location const&>(),
339+
std::declval<std::uint8_t>()
340+
))>>: std::true_type{};
341+
342+
template<typename T, typename U = void>
343+
struct has_parse_float: std::false_type{};
371344
template<typename T>
372-
using has_parse_float = decltype(has_parse_float_impl::check<T>(nullptr));
345+
struct has_parse_float<T, cxx::void_t<decltype(std::declval<T>().parse_float(
346+
std::declval<std::string const&>(),
347+
std::declval<::toml::source_location const&>(),
348+
std::declval<bool>()
349+
))>>: std::true_type{};
373350

374351
template<typename T>
375352
using is_type_config = cxx::conjunction<

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ set(TOML11_TEST_NAMES
2121
test_parse_inline_table
2222
test_parse_table_keys
2323
test_parse_table
24+
test_parse
2425
test_result
2526
test_scanner
2627
test_serialize

tests/test_parse.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
2+
#include "doctest.h"
3+
4+
#include <toml.hpp>
5+
6+
#include <clocale>
7+
8+
TEST_CASE("testing toml::parse(file)")
9+
{
10+
using namespace toml::literals::toml_literals;
11+
12+
const std::string spec_example(R"(# This is a TOML document
13+
14+
title = "TOML Example"
15+
16+
[owner]
17+
name = "Tom Preston-Werner"
18+
dob = 1979-05-27T07:32:00-08:00
19+
20+
[database]
21+
enabled = true
22+
ports = [ 8000, 8001, 8002 ]
23+
data = [ ["delta", "phi"], [3.14] ]
24+
temp_targets = { cpu = 79.5, case = 72.0 }
25+
26+
[servers]
27+
28+
[servers.alpha]
29+
ip = "10.0.0.1"
30+
role = "frontend"
31+
32+
[servers.beta]
33+
ip = "10.0.0.2"
34+
role = "backend"
35+
)");
36+
37+
{
38+
std::ofstream ofs("test_parse.toml");
39+
ofs << spec_example;
40+
}
41+
42+
const auto u = toml::parse_str(spec_example);
43+
const auto v = toml::parse("test_parse.toml");
44+
45+
CHECK_EQ(u, v);
46+
47+
CHECK_EQ(toml::find<int>(v, "database", "ports", 0), 8000);
48+
CHECK_EQ(toml::find<int>(v, "database", "ports", 1), 8001);
49+
CHECK_EQ(toml::find<int>(v, "database", "ports", 2), 8002);
50+
}

0 commit comments

Comments
 (0)