From 69875c238eece34a3644b1d2208b73d06445ff62 Mon Sep 17 00:00:00 2001 From: red0124 <75804778+red0124@users.noreply.github.com> Date: Tue, 12 Mar 2024 18:31:24 +0100 Subject: [PATCH] Resolve clang-tidy warnings (#48) * Resolve clang-tidy warnings, update single_header_generator.py * Update single header test, resolve additional clang-tidy warnings --- .gitignore | 2 +- include/ss/common.hpp | 22 ++++--- include/ss/converter.hpp | 9 +-- include/ss/exception.hpp | 4 +- include/ss/extract.hpp | 19 ++++-- include/ss/function_traits.hpp | 1 - include/ss/parser.hpp | 43 +++++++----- include/ss/splitter.hpp | 6 +- include/ss/type_traits.hpp | 6 +- script/single_header_generator.py | 9 ++- ssp.hpp | 105 ++++++++++++++++++------------ test/test_single_header.sh | 14 ++-- test/test_single_header_main.txt | 12 ++++ 13 files changed, 160 insertions(+), 92 deletions(-) create mode 100644 test/test_single_header_main.txt diff --git a/.gitignore b/.gitignore index 1fadaf3..55f29f8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ compile_commands.json .clang-format .clang-tidy -.ccls-cache/* +.ccls-cache/ .cache/ experiment/ build/ diff --git a/include/ss/common.hpp b/include/ss/common.hpp index 6a7ee62..61b0983 100644 --- a/include/ss/common.hpp +++ b/include/ss/common.hpp @@ -1,11 +1,15 @@ #pragma once #include -#include #include #include #include #include +#if !__unix__ +#include +#include +#endif + namespace ss { struct none {}; @@ -17,13 +21,13 @@ constexpr inline auto default_delimiter = ","; constexpr inline auto get_line_initial_buffer_size = 128; template -inline void assert_string_error_defined() { +void assert_string_error_defined() { static_assert(StringError, "'string_error' needs to be enabled to use 'error_msg'"); } template -inline void assert_throw_on_error_not_defined() { +void assert_throw_on_error_not_defined() { static_assert(!ThrowOnError, "cannot handle errors manually if " "'throw_on_error' is enabled"); } @@ -46,7 +50,7 @@ inline ssize_t get_line_file(char*& lineptr, size_t& n, FILE* file) { using ssize_t = intptr_t; inline ssize_t get_line_file(char*& lineptr, size_t& n, FILE* file) { - char buff[get_line_initial_buffer_size]; + std::array buff; if (lineptr == nullptr || n < sizeof(buff)) { size_t new_n = sizeof(buff); @@ -57,9 +61,9 @@ inline ssize_t get_line_file(char*& lineptr, size_t& n, FILE* file) { lineptr[0] = '\0'; size_t line_used = 0; - while (std::fgets(buff, sizeof(buff), file) != nullptr) { + while (std::fgets(buff.data(), sizeof(buff), file) != nullptr) { line_used = std::strlen(lineptr); - size_t buff_used = std::strlen(buff); + size_t buff_used = std::strlen(buff.data()); if (n <= buff_used + line_used) { size_t new_n = n * 2; @@ -67,7 +71,7 @@ inline ssize_t get_line_file(char*& lineptr, size_t& n, FILE* file) { n = new_n; } - std::memcpy(lineptr + line_used, buff, buff_used); + std::memcpy(lineptr + line_used, buff.data(), buff_used); line_used += buff_used; lineptr[line_used] = '\0'; @@ -89,7 +93,7 @@ inline ssize_t get_line_buffer(char*& lineptr, size_t& n, } if (lineptr == nullptr || n < get_line_initial_buffer_size) { - auto new_lineptr = static_cast( + auto* new_lineptr = static_cast( strict_realloc(lineptr, get_line_initial_buffer_size)); lineptr = new_lineptr; n = get_line_initial_buffer_size; @@ -122,7 +126,7 @@ inline std::tuple get_line(char*& buffer, size_t& buffer_size, FILE* file, const char* const csv_data_buffer, size_t csv_data_size, size_t& curr_char) { - ssize_t ssize; + ssize_t ssize = 0; if (file) { ssize = get_line_file(buffer, buffer_size, file); curr_char += ssize; diff --git a/include/ss/converter.hpp b/include/ss/converter.hpp index 0a1a1f8..7855ea2 100644 --- a/include/ss/converter.hpp +++ b/include/ss/converter.hpp @@ -224,8 +224,9 @@ private: } std::string error_sufix(const string_range msg, size_t pos) const { + constexpr static auto reserve_size = 32; std::string error; - error.reserve(32); + error.reserve(reserve_size); error.append("at column ") .append(std::to_string(pos + 1)) .append(": \'") @@ -391,7 +392,7 @@ private: //////////////// bool columns_mapped() const { - return column_mappings_.size() != 0; + return !column_mappings_.empty(); } size_t column_position(size_t tuple_position) const { @@ -404,7 +405,7 @@ private: // assumes positions are valid and the vector is not empty void set_column_mapping(std::vector positions, size_t number_of_columns) { - column_mappings_ = positions; + column_mappings_ = std::move(positions); number_of_columns_ = number_of_columns; } @@ -490,7 +491,7 @@ private: friend class parser; std::vector column_mappings_; - size_t number_of_columns_; + size_t number_of_columns_{0}; }; } /* namespace ss */ diff --git a/include/ss/exception.hpp b/include/ss/exception.hpp index 3733d19..652967c 100644 --- a/include/ss/exception.hpp +++ b/include/ss/exception.hpp @@ -12,10 +12,10 @@ class exception : public std::exception { std::string msg_; public: - exception(const std::string& msg): msg_{msg} { + exception(std::string msg): msg_{std::move(msg)} { } - virtual char const* what() const noexcept { + char const* what() const noexcept override { return msg_.c_str(); } }; diff --git a/include/ss/extract.hpp b/include/ss/extract.hpp index 99fa2e7..3c2f82e 100644 --- a/include/ss/extract.hpp +++ b/include/ss/extract.hpp @@ -2,8 +2,8 @@ #include "type_traits.hpp" #include +#include #include -#include #include #include #include @@ -14,6 +14,7 @@ #else #include #include +#include #endif namespace ss { @@ -45,16 +46,17 @@ std::enable_if_t, std::optional> to_num( "Conversion to long double is disabled"); constexpr static auto buff_max = 64; - char short_buff[buff_max]; + std::array short_buff; + size_t string_range = std::distance(begin, end); std::string long_buff; - char* buff; + char* buff = nullptr; if (string_range > buff_max) { long_buff = std::string{begin, end}; buff = long_buff.data(); } else { - buff = short_buff; + buff = short_buff.data(); buff[string_range] = '\0'; std::copy_n(begin, string_range, buff); } @@ -92,6 +94,8 @@ struct numeric_wrapper { numeric_wrapper& operator=(numeric_wrapper&&) = default; numeric_wrapper& operator=(const numeric_wrapper&) = default; + ~numeric_wrapper() = default; + numeric_wrapper(T other) : value{other} { } @@ -215,10 +219,13 @@ inline bool extract(const char* begin, const char* end, bool& value) { return false; } } else { + constexpr static auto true_size = 4; + constexpr static auto false_size = 5; size_t size = end - begin; - if (size == 4 && std::strncmp(begin, "true", size) == 0) { + if (size == true_size && std::strncmp(begin, "true", size) == 0) { value = true; - } else if (size == 5 && std::strncmp(begin, "false", size) == 0) { + } else if (size == false_size && + std::strncmp(begin, "false", size) == 0) { value = false; } else { return false; diff --git a/include/ss/function_traits.hpp b/include/ss/function_traits.hpp index 945a97e..b71df1b 100644 --- a/include/ss/function_traits.hpp +++ b/include/ss/function_traits.hpp @@ -2,7 +2,6 @@ #include #include -#include namespace ss { diff --git a/include/ss/parser.hpp b/include/ss/parser.hpp index 86b3a7b..5fbf647 100644 --- a/include/ss/parser.hpp +++ b/include/ss/parser.hpp @@ -5,7 +5,6 @@ #include "exception.hpp" #include "extract.hpp" #include "restrictions.hpp" -#include #include #include #include @@ -33,9 +32,8 @@ class parser { constexpr static bool ignore_empty = setup::ignore_empty; public: - parser(const std::string& file_name, - const std::string& delim = ss::default_delimiter) - : file_name_{file_name}, reader_{file_name_, delim} { + parser(std::string file_name, std::string delim = ss::default_delimiter) + : file_name_{std::move(file_name)}, reader_{file_name_, delim} { if (reader_.file_) { read_line(); if constexpr (ignore_header) { @@ -68,6 +66,7 @@ public: parser(parser&& other) = default; parser& operator=(parser&& other) = default; + ~parser() = default; parser() = delete; parser(const parser& other) = delete; @@ -237,6 +236,10 @@ public: iterator(const iterator& other) = default; iterator(iterator&& other) = default; + ~iterator() = default; + + iterator& operator=(const iterator& other) = delete; + iterator& operator=(iterator&& other) = delete; value& operator*() { return value_; @@ -261,8 +264,10 @@ public: return *this; } - iterator& operator++(int) { - return ++*this; + iterator operator++(int) { + auto result = *this; + ++*this; + return result; } friend bool operator==(const iterator& lhs, const iterator& rhs) { @@ -326,7 +331,7 @@ public: Fun&& fun = none{}) { using Value = no_void_validator_tup_t; std::optional value; - try_convert_and_invoke(value, fun); + try_convert_and_invoke(value, std::forward(fun)); return composite_with(std::move(value)); } @@ -335,7 +340,7 @@ public: template composite> or_object(Fun&& fun = none{}) { std::optional value; - try_convert_and_invoke(value, fun); + try_convert_and_invoke(value, std::forward(fun)); return composite_with(std::move(value)); } @@ -443,7 +448,8 @@ private: using Ret = decltype(try_invoke_impl(arg, std::forward(fun))); constexpr bool returns_void = std::is_same_v; if constexpr (!returns_void) { - if (!try_invoke_impl(arg, std::forward(fun))) { + if (!try_invoke_impl(std::forward(arg), + std::forward(fun))) { handle_error_failed_check(); } } else { @@ -478,7 +484,7 @@ private: if (valid()) { try_invoke(*value, std::forward(fun)); } - return {valid() ? std::move(value) : std::nullopt, *this}; + return {valid() ? std::forward(value) : std::nullopt, *this}; } //////////////// @@ -674,17 +680,18 @@ private: } struct reader { - reader(const std::string& file_name_, const std::string& delim) - : delim_{delim}, file_{std::fopen(file_name_.c_str(), "rb")} { + reader(const std::string& file_name_, std::string delim) + : delim_{std::move(delim)}, + file_{std::fopen(file_name_.c_str(), "rb")} { } reader(const char* const buffer, size_t csv_data_size, - const std::string& delim) - : delim_{delim}, csv_data_buffer_{buffer}, + std::string delim) + : delim_{std::move(delim)}, csv_data_buffer_{buffer}, csv_data_size_{csv_data_size} { } - reader(reader&& other) + reader(reader&& other) noexcept : buffer_{other.buffer_}, next_line_buffer_{other.next_line_buffer_}, helper_buffer_{other.helper_buffer_}, @@ -705,7 +712,7 @@ private: other.file_ = nullptr; } - reader& operator=(reader&& other) { + reader& operator=(reader&& other) noexcept { if (this != &other) { buffer_ = other.buffer_; next_line_buffer_ = other.next_line_buffer_; @@ -853,7 +860,7 @@ private: } bool escaped_eol(size_t size) { - const char* curr; + const char* curr = nullptr; for (curr = next_line_buffer_ + size - 1; curr >= next_line_buffer_ && setup::escape::match(*curr); @@ -899,7 +906,7 @@ private: size_t& buffer_size, const char* const second, size_t second_size) { buffer_size = first_size + second_size + 3; - auto new_first = static_cast( + auto* new_first = static_cast( strict_realloc(static_cast(first), buffer_size)); first = new_first; diff --git a/include/ss/splitter.hpp b/include/ss/splitter.hpp index ea00c87..d6278ff 100644 --- a/include/ss/splitter.hpp +++ b/include/ss/splitter.hpp @@ -2,7 +2,6 @@ #include "common.hpp" #include "exception.hpp" #include "setup.hpp" -#include "type_traits.hpp" #include #include #include @@ -321,8 +320,9 @@ private: trim_left_if_enabled(begin_); - for (done_ = false; !done_; read(delim)) - ; + for (done_ = false; !done_;) { + read(delim); + } return split_data_; } diff --git a/include/ss/type_traits.hpp b/include/ss/type_traits.hpp index 1a1d2ee..f56ee94 100644 --- a/include/ss/type_traits.hpp +++ b/include/ss/type_traits.hpp @@ -34,7 +34,11 @@ struct left_of_impl; template struct left_of_impl { - static_assert(N < 128, "recursion limit reached"); +private: + constexpr static auto recursion_limit = 128; + +public: + static_assert(N < recursion_limit, "recursion limit reached"); static_assert(N != 0, "cannot take the whole tuple"); using type = tup_cat_t::type>; }; diff --git a/script/single_header_generator.py b/script/single_header_generator.py index 91c9dcc..0fd5c2c 100755 --- a/script/single_header_generator.py +++ b/script/single_header_generator.py @@ -14,14 +14,21 @@ headers = ['type_traits.hpp', combined_file = [] includes = [] +in_pp_block = False for header in headers: with open(headers_dir + header) as f: for line in f.read().splitlines(): + if '#if ' in line: + in_pp_block = True + + if '#endif' in line: + in_pp_block = False + if '#include "' in line or '#include struct left_of_impl { - static_assert(N < 128, "recursion limit reached"); +private: + constexpr static auto recursion_limit = 128; + +public: + static_assert(N < recursion_limit, "recursion limit reached"); static_assert(N != 0, "cannot take the whole tuple"); using type = tup_cat_t::type>; }; @@ -405,10 +409,10 @@ class exception : public std::exception { std::string msg_; public: - exception(const std::string& msg): msg_{msg} { + exception(std::string msg): msg_{std::move(msg)} { } - virtual char const* what() const noexcept { + char const* what() const noexcept override { return msg_.c_str(); } }; @@ -617,6 +621,11 @@ struct ne { } /* namespace ss */ +#if !__unix__ +#include +#include +#endif + namespace ss { struct none {}; @@ -628,13 +637,13 @@ constexpr inline auto default_delimiter = ","; constexpr inline auto get_line_initial_buffer_size = 128; template -inline void assert_string_error_defined() { +void assert_string_error_defined() { static_assert(StringError, "'string_error' needs to be enabled to use 'error_msg'"); } template -inline void assert_throw_on_error_not_defined() { +void assert_throw_on_error_not_defined() { static_assert(!ThrowOnError, "cannot handle errors manually if " "'throw_on_error' is enabled"); } @@ -657,7 +666,7 @@ inline ssize_t get_line_file(char*& lineptr, size_t& n, FILE* file) { using ssize_t = intptr_t; inline ssize_t get_line_file(char*& lineptr, size_t& n, FILE* file) { - char buff[get_line_initial_buffer_size]; + std::array buff; if (lineptr == nullptr || n < sizeof(buff)) { size_t new_n = sizeof(buff); @@ -668,9 +677,9 @@ inline ssize_t get_line_file(char*& lineptr, size_t& n, FILE* file) { lineptr[0] = '\0'; size_t line_used = 0; - while (std::fgets(buff, sizeof(buff), file) != nullptr) { + while (std::fgets(buff.data(), sizeof(buff), file) != nullptr) { line_used = std::strlen(lineptr); - size_t buff_used = std::strlen(buff); + size_t buff_used = std::strlen(buff.data()); if (n <= buff_used + line_used) { size_t new_n = n * 2; @@ -678,7 +687,7 @@ inline ssize_t get_line_file(char*& lineptr, size_t& n, FILE* file) { n = new_n; } - std::memcpy(lineptr + line_used, buff, buff_used); + std::memcpy(lineptr + line_used, buff.data(), buff_used); line_used += buff_used; lineptr[line_used] = '\0'; @@ -700,7 +709,7 @@ inline ssize_t get_line_buffer(char*& lineptr, size_t& n, } if (lineptr == nullptr || n < get_line_initial_buffer_size) { - auto new_lineptr = static_cast( + auto* new_lineptr = static_cast( strict_realloc(lineptr, get_line_initial_buffer_size)); lineptr = new_lineptr; n = get_line_initial_buffer_size; @@ -733,7 +742,7 @@ inline std::tuple get_line(char*& buffer, size_t& buffer_size, FILE* file, const char* const csv_data_buffer, size_t csv_data_size, size_t& curr_char) { - ssize_t ssize; + ssize_t ssize = 0; if (file) { ssize = get_line_file(buffer, buffer_size, file); curr_char += ssize; @@ -1359,8 +1368,9 @@ private: trim_left_if_enabled(begin_); - for (done_ = false; !done_; read(delim)) - ; + for (done_ = false; !done_;) { + read(delim); + } return split_data_; } @@ -1552,16 +1562,17 @@ std::enable_if_t, std::optional> to_num( "Conversion to long double is disabled"); constexpr static auto buff_max = 64; - char short_buff[buff_max]; + std::array short_buff; + size_t string_range = std::distance(begin, end); std::string long_buff; - char* buff; + char* buff = nullptr; if (string_range > buff_max) { long_buff = std::string{begin, end}; buff = long_buff.data(); } else { - buff = short_buff; + buff = short_buff.data(); buff[string_range] = '\0'; std::copy_n(begin, string_range, buff); } @@ -1599,6 +1610,8 @@ struct numeric_wrapper { numeric_wrapper& operator=(numeric_wrapper&&) = default; numeric_wrapper& operator=(const numeric_wrapper&) = default; + ~numeric_wrapper() = default; + numeric_wrapper(T other) : value{other} { } @@ -1649,7 +1662,7 @@ template struct unsupported_type { constexpr static bool value = false; }; -} /* namespace error */ +} /* namespace errors */ template std::enable_if_t && !std::is_floating_point_v && @@ -1722,10 +1735,13 @@ inline bool extract(const char* begin, const char* end, bool& value) { return false; } } else { + constexpr static auto true_size = 4; + constexpr static auto false_size = 5; size_t size = end - begin; - if (size == 4 && std::strncmp(begin, "true", size) == 0) { + if (size == true_size && std::strncmp(begin, "true", size) == 0) { value = true; - } else if (size == 5 && std::strncmp(begin, "false", size) == 0) { + } else if (size == false_size && + std::strncmp(begin, "false", size) == 0) { value = false; } else { return false; @@ -1971,8 +1987,9 @@ private: } std::string error_sufix(const string_range msg, size_t pos) const { + constexpr static auto reserve_size = 32; std::string error; - error.reserve(32); + error.reserve(reserve_size); error.append("at column ") .append(std::to_string(pos + 1)) .append(": \'") @@ -2138,7 +2155,7 @@ private: //////////////// bool columns_mapped() const { - return column_mappings_.size() != 0; + return !column_mappings_.empty(); } size_t column_position(size_t tuple_position) const { @@ -2151,7 +2168,7 @@ private: // assumes positions are valid and the vector is not empty void set_column_mapping(std::vector positions, size_t number_of_columns) { - column_mappings_ = positions; + column_mappings_ = std::move(positions); number_of_columns_ = number_of_columns; } @@ -2237,7 +2254,7 @@ private: friend class parser; std::vector column_mappings_; - size_t number_of_columns_; + size_t number_of_columns_{0}; }; } /* namespace ss */ @@ -2264,9 +2281,8 @@ class parser { constexpr static bool ignore_empty = setup::ignore_empty; public: - parser(const std::string& file_name, - const std::string& delim = ss::default_delimiter) - : file_name_{file_name}, reader_{file_name_, delim} { + parser(std::string file_name, std::string delim = ss::default_delimiter) + : file_name_{std::move(file_name)}, reader_{file_name_, delim} { if (reader_.file_) { read_line(); if constexpr (ignore_header) { @@ -2299,6 +2315,7 @@ public: parser(parser&& other) = default; parser& operator=(parser&& other) = default; + ~parser() = default; parser() = delete; parser(const parser& other) = delete; @@ -2468,6 +2485,10 @@ public: iterator(const iterator& other) = default; iterator(iterator&& other) = default; + ~iterator() = default; + + iterator& operator=(const iterator& other) = delete; + iterator& operator=(iterator&& other) = delete; value& operator*() { return value_; @@ -2492,8 +2513,10 @@ public: return *this; } - iterator& operator++(int) { - return ++*this; + iterator operator++(int) { + auto result = *this; + ++*this; + return result; } friend bool operator==(const iterator& lhs, const iterator& rhs) { @@ -2557,7 +2580,7 @@ public: Fun&& fun = none{}) { using Value = no_void_validator_tup_t; std::optional value; - try_convert_and_invoke(value, fun); + try_convert_and_invoke(value, std::forward(fun)); return composite_with(std::move(value)); } @@ -2566,7 +2589,7 @@ public: template composite> or_object(Fun&& fun = none{}) { std::optional value; - try_convert_and_invoke(value, fun); + try_convert_and_invoke(value, std::forward(fun)); return composite_with(std::move(value)); } @@ -2674,7 +2697,8 @@ private: using Ret = decltype(try_invoke_impl(arg, std::forward(fun))); constexpr bool returns_void = std::is_same_v; if constexpr (!returns_void) { - if (!try_invoke_impl(arg, std::forward(fun))) { + if (!try_invoke_impl(std::forward(arg), + std::forward(fun))) { handle_error_failed_check(); } } else { @@ -2709,7 +2733,7 @@ private: if (valid()) { try_invoke(*value, std::forward(fun)); } - return {valid() ? std::move(value) : std::nullopt, *this}; + return {valid() ? std::forward(value) : std::nullopt, *this}; } //////////////// @@ -2905,17 +2929,18 @@ private: } struct reader { - reader(const std::string& file_name_, const std::string& delim) - : delim_{delim}, file_{std::fopen(file_name_.c_str(), "rb")} { + reader(const std::string& file_name_, std::string delim) + : delim_{std::move(delim)}, + file_{std::fopen(file_name_.c_str(), "rb")} { } reader(const char* const buffer, size_t csv_data_size, - const std::string& delim) - : delim_{delim}, csv_data_buffer_{buffer}, + std::string delim) + : delim_{std::move(delim)}, csv_data_buffer_{buffer}, csv_data_size_{csv_data_size} { } - reader(reader&& other) + reader(reader&& other) noexcept : buffer_{other.buffer_}, next_line_buffer_{other.next_line_buffer_}, helper_buffer_{other.helper_buffer_}, @@ -2936,7 +2961,7 @@ private: other.file_ = nullptr; } - reader& operator=(reader&& other) { + reader& operator=(reader&& other) noexcept { if (this != &other) { buffer_ = other.buffer_; next_line_buffer_ = other.next_line_buffer_; @@ -3084,7 +3109,7 @@ private: } bool escaped_eol(size_t size) { - const char* curr; + const char* curr = nullptr; for (curr = next_line_buffer_ + size - 1; curr >= next_line_buffer_ && setup::escape::match(*curr); @@ -3130,7 +3155,7 @@ private: size_t& buffer_size, const char* const second, size_t second_size) { buffer_size = first_size + second_size + 3; - auto new_first = static_cast( + auto* new_first = static_cast( strict_realloc(static_cast(first), buffer_size)); first = new_first; diff --git a/test/test_single_header.sh b/test/test_single_header.sh index 8a2bb91..bd47386 100755 --- a/test/test_single_header.sh +++ b/test/test_single_header.sh @@ -3,12 +3,14 @@ set -x set -e -python3 script/single_header_generator.py > ssp.cpp +TMP_HDR=test_single_header.hpp +TMP_SRC=test_single_header.cpp +TMP_BIN=test_single_header -echo 'int main(){ ss::parser p{""}; p.get_next(); return 0; }' \ - >> ssp.cpp +python3 script/single_header_generator.py > ${TMP_HDR} +cat ${TMP_HDR} test/test_single_header_main.txt > ${TMP_SRC} -g++ -std=c++17 ssp.cpp -o ssp.bin -Wall -Wextra -./ssp.bin +g++ -std=c++17 ${TMP_SRC} -o ${TMP_BIN} -Wall -Wextra +./${TMP_BIN} -rm ssp.cpp ssp.bin +rm ${TMP_HDR} ${TMP_SRC} ${TMP_BIN} diff --git a/test/test_single_header_main.txt b/test/test_single_header_main.txt new file mode 100644 index 0000000..77d8c6c --- /dev/null +++ b/test/test_single_header_main.txt @@ -0,0 +1,12 @@ +int main() { + using quote = ss::quote<'"'>; + using escape = ss::escape<'\\'>; + using trim = ss::trim<' '>; + + std::string data = "1,string,2.34,c"; + + ss::parser p{data.c_str(), data.size()}; + auto tup = p.get_next>(); + + return 0; +}