Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
template <char... Chars>
String<Chars...> operator""_conststr() {
return String<Chars...>();
}Проще и не менее удобно IMO…constexpr auto operator""_conststr(const char* data, const size_t size) {
return ...;
}
using FooString = decltype("Foo"_conststr);
charов, если… эта строка — это число! Великолепная идея, блин: сделать фичу — но так, чтобы использовать её можно было ровно тогда, когда она никому нафиг не нужна… а то, что нужно — это, оказывается… GNU'сное расширение…Судя по вот этому trip report-у, в C++20 включили предложение p0424r2: String literals as template parameters
Мне очень нравится clang и я предпочитаю везде использовать именно его, но я не люблю писать compiler-specific код, не предусмотренный стандартом. По моему опыту это имеет свойство через некоторое время превращаться в очередные подводные грабли.Не в тех случаях, когда это включено в следующую версию стандарта, как в данном случае. Спасибо eao197!
#include <iostream>
#include <utility>
template <char... symbols>
struct Constexpr_string
{
static constexpr char value[] = { symbols... };
};
template <typename Lambda_type, std::size_t... indexes>
constexpr auto get_string(Lambda_type function, std::index_sequence<indexes...>)
{
return Constexpr_string<function()[indexes]...>();
}
template <std::size_t N, typename Lambda_type, typename Indices = std::make_index_sequence<N>>
constexpr auto get_string(Lambda_type function)
{
return get_string(function, Indices{});
}
constexpr size_t length(const char* str)
{
return (*str == 0) ? 0 : length(str + 1) + 1;
}
template <typename Lambda_type>
constexpr auto get_string(Lambda_type function)
{
return get_string<length(function())>(function);
}
int main()
{
auto s = get_string([](){ return "lambda"; });
std::cout << decltype(s)::value << std::endl;
}Мне было бы очень интересно услышать о возможных применениях этого механизма, отличных от тех, что придумал я.
Но вы же тоже не привели примеры того, где это может пригодиться :)
Конкретные задачи, которые я решал — отдельный вопрос.
Наверное стоило всё-таки дописать эту часть.
template<char ... c>
class String { ... };
String<"test">{};
constexpr const char _test[] = "12345";
template <const char String[]>
struct CString
{
static inline constexpr const std::string_view str{String};
static inline constexpr const char *psz = String;
static constexpr bool verify() noexcept
{
for (size_t i = 1, n = str.size(); i < n; ++i)
if (psz[i - 1] > psz[i])
return false;
return true;
}
static_assert(verify());
};
std::cout << CString<_test>::str << CString<_test>::psz;
std::cout << CString<"123456">::str << CString<_test>::psz;int main()
{
static constexpr const char _test[] = "12345";
std::cout << CString<_test>::str << CString<_test>::psz;
return 0;
}
Мне было бы очень интересно услышать о возможных применениях этого механизма, отличных от тех, что придумал я.
myprintf("Hello % world %!\n", 1, "123") printf("Hello %d world %s\n", 1, "123");Вы реализовали форматирование в своем логгере?
> ./logging-bench
2019-01-31 18:37:47
Running ./logging-bench
Run on (8 X 4200 MHz CPU s)
CPU Caches:
L1 Data 32K (x4)
L1 Instruction 32K (x4)
L2 Unified 256K (x4)
L3 Unified 8192K (x1)
***WARNING*** Library was built as DEBUG. Timings may be affected.
--------------------------------------------------------------
Benchmark Time CPU Iterations
--------------------------------------------------------------
bmLoggingSingleString 121 ns 120 ns 5835101
bmLogging1Arg 134 ns 134 ns 5213675
bmLogging2Arg 156 ns 155 ns 4504116
bmLogging3Arg 218 ns 215 ns 3255618
bmLogging5StringArgs 538 ns 526 ns 1346569
bmLogging2ArgWithSpecs 168 ns 164 ns 4299307
#include <cstdlib>
#include <array>
template<char ... chars>
struct ct_string
{
constexpr static size_t size()
{
return sizeof...(chars);
}
constexpr static auto get()
{
return std::array<char, size()>{ {chars ...} };
}
constexpr static auto to_string()
{
return std::string{chars ...};
}
};
template<size_t N, typename T, char ...>
struct ct_maker_details;
template<size_t N, char ... chars, char first, char ... tail>
struct ct_maker_details<N, ct_string<chars...>, first, tail...>
{
static constexpr auto make()
{
if constexpr(sizeof...(chars) == N)
return ct_string<chars ...>{};
else
return ct_maker_details<N, ct_string<chars ..., first>, tail ...>::make();
};
};
template<size_t N, char ... chars>
constexpr auto make_ct_string()
{
return ct_maker_details<N, ct_string<>, chars...>::make();
};
template<size_t size>
constexpr size_t str_size(const char (&)[size])
{
return size;
}
#define STR_TO_CHARS(str) STR_TO_CHARS_(str, str_size(str))
#define STR_TO_CHARS_(str, N) \
str[IC(0, N)], str[IC(1, N)], str[IC(2, N)], str[IC(3, N)], str[IC(4, N)], str[IC(5, N)], str[IC(6, N)], str[IC(7, N)], str[IC(8, N)], str[IC(9, N)], \
str[IC(10, N)], str[IC(11, N)], str[IC(12, N)], str[IC(13, N)], str[IC(14, N)], str[IC(15, N)], str[IC(16, N)], str[IC(17, N)], str[IC(18, N)], str[IC(19, N)], \
str[IC(20, N)], str[IC(21, N)], str[IC(22, N)], str[IC(23, N)], str[IC(24, N)], str[IC(25, N)], str[IC(26, N)], str[IC(27, N)], str[IC(28, N)], str[IC(29, N)], \
str[IC(30, N)], str[IC(31, N)], str[IC(32, N)], str[IC(33, N)], str[IC(34, N)], str[IC(35, N)], str[IC(36, N)], str[IC(37, N)], str[IC(38, N)], str[IC(39, N)], \
str[IC(40, N)], str[IC(41, N)], str[IC(42, N)], str[IC(43, N)], str[IC(44, N)], str[IC(45, N)], str[IC(46, N)], str[IC(47, N)], str[IC(48, N)], str[IC(49, N)], \
str[IC(50, N)], str[IC(51, N)], str[IC(52, N)], str[IC(53, N)], str[IC(54, N)], str[IC(55, N)], str[IC(56, N)], str[IC(57, N)], str[IC(58, N)], str[IC(59, N)], \
str[IC(60, N)], str[IC(61, N)], str[IC(62, N)], str[IC(63, N)], str[IC(64, N)], str[IC(65, N)], str[IC(66, N)], str[IC(67, N)], str[IC(68, N)], str[IC(69, N)], \
str[IC(70, N)], str[IC(71, N)], str[IC(72, N)], str[IC(73, N)], str[IC(74, N)], str[IC(75, N)], str[IC(76, N)], str[IC(77, N)], str[IC(78, N)], str[IC(79, N)], \
str[IC(80, N)], str[IC(81, N)], str[IC(82, N)], str[IC(83, N)], str[IC(84, N)], str[IC(85, N)], str[IC(86, N)], str[IC(87, N)], str[IC(88, N)], str[IC(89, N)], \
str[IC(90, N)], str[IC(91, N)], str[IC(92, N)], str[IC(93, N)], str[IC(94, N)], str[IC(95, N)], str[IC(96, N)], str[IC(97, N)], str[IC(98, N)], str[IC(99, N)], \
str[IC(100, N)], str[IC(101, N)], str[IC(102, N)], str[IC(103, N)], str[IC(104, N)], str[IC(105, N)], str[IC(106, N)], str[IC(107, N)], str[IC(108, N)], str[IC(109, N)], \
str[IC(110, N)], str[IC(111, N)], str[IC(112, N)], str[IC(113, N)], str[IC(114, N)], str[IC(115, N)], str[IC(116, N)], str[IC(117, N)], str[IC(118, N)], str[IC(119, N)], \
str[IC(120, N)], str[IC(121, N)], str[IC(122, N)], str[IC(123, N)], str[IC(124, N)], str[IC(125, N)], str[IC(126, N)], str[IC(127, N)]
#define IC(index, count) (index) >= (count) ? ((count) - 1) : (index)
#define CT_STR(str) decltype(make_ct_string<str_size(str), STR_TO_CHARS(str)>())
#include <iostream>
template<typename T>
void foo()
{
std::cout << "size=" << T::size() << " string: " << T::to_string() << std::endl;
};
int main()
{
foo<CT_STR("Hello world!!!!")>();
return 0;
}
Помещаем строки в параметры шаблонов