Шаблон вычета руководство для функции?

Я пытаюсь написать некоторые шаблонные функции, которые принимают либо std::basic_string или массив символов, из которого basic_string может быть построен.

Мое текущее решение:

#include <string>

template<typename CharT>
void foo(std::basic_string<CharT> str)
{
(void)str; // do something with str
}
template<typename CharT>
void foo(CharT const * arr)
{
return foo(std::basic_string<CharT>{arr});
}

int main(void)
{
foo("hello");
foo(std::string{ "hello" });
foo(L"hello");
foo(std::wstring{ L"hello" });
}

Но это означает, что для каждой функции мне нужно написать другую функцию, которая вызывает первую. Это довольно раздражает; Есть ли более простой способ сделать это? Может быть, это может быть руководство по выводу шаблона, но, насколько я знаю, его не существует для функций, только для классов.

Первая шаблонная функция не достаточна, потому что вывод шаблона не выполняется: компилятор не может вывести CharT в std::basic_string<CharT> от CharT const *, Вот почему мне нужен более простой способ сообщить об этом компилятору.

4

Решение

После нескольких исследований лучше всего использовать imo C ++ 17. std::basic_string_view:

template<typename CharT>
void foo(std::basic_string_view<CharT> str)
{
(void)str; // do something with str ...
// while remembering that string_view does not own the string
}

Так что забудьте о более раннем объяснении ниже, если у вас есть доступ к 17-компилятору C ++.



Здесь нужно рассмотреть два случая. первый случай вы не хотите делать что-то особенное с базовой строкой, а применяете только те методы, которые доступны для char-array (и просто хочу убедиться, что он вызывается правильно, независимо от параметров). В этом случае я бы просто использовал общий параметр шаблона:

template<typename string_type
/* possibly some SFINAE to allow/disallow certain types */>
auto foo(string_type s)
{
std::cout << s << std::endl;
}

Второй случай в том, что вы действительно хотите сделать какую-то специальную операцию со строкой, которой нет в массиве char. В этом случае вам нужна перегрузка для basic_string, но вы, вероятно, хотите написать это только один раз, а не для каждой функции, которую вы используете. Это то, что следующее string_invoker класс пытается это сделать (но он все еще нуждается в некотором улучшении, просто работая над этим):

template<typename method>
struct string_invoker_impl
{
string_invoker_impl(method m) : m(m) {}

template<typename CharT>
auto operator()(std::basic_string<CharT> str) const
{
return m(str);
}

template<typename CharT>
auto operator()(CharT const * arr) const
{
return operator()(std::basic_string<CharT>{arr});
}

//possibly further methods for non-const array's, modification, etc.

method m;
};

auto string_invoker = [](auto m) { return string_invoker_impl<decltype(m)>{m}; };

auto foo_impl = [](auto str) {std::cout<< str <<std::endl; };
auto foo = string_invoker(foo_impl);

//you  can merge the previous two calls also in a single one:
//auto foo = string_invoker( [](auto str) {std::cout<< str <<std::endl; });int main(void)
{
foo("hello");
foo(std::string{ "hello" });
//foo(L"hello");                      //need std::wcout, thus it fails with std::cout
//but it's no general problem, just overload your foo_impl function
//foo(std::wstring{ L"hello" });
}

DEMO

4

Другие решения

Просто укусите пулю и используйте 2 перегрузки. Любое умное решение (которое как davidhigh показал, что существуют) только добавит ненужную сложность, потенциальные ошибки и путаницу для следующего читателя.

Вы пишете только один раз, но читаете несколько раз. Небольшое неудобство в написании 1 строки перегрузки тела стоит того, чтобы противостоять не-идиоматическим запутанным умный способ.

Не поймите меня неправильно, я люблю находить эти умные решения в C ++, но если бы я нашел это решение в производственном коде, мне потребовалось бы несколько хороших минут, чтобы просто выяснить, что это за хрень и что он делает, только чтобы выяснить, что он просто делает то, что должно было быть очень простым сложным образом, я бы … ну, скажем так, я бы не сказал ничего хорошего об авторе кода. Лень при написании кода обойдется вам дороже, если вы будете поддерживать, отлаживать, расширять или даже использовать код.

Напишите простой, идиоматичный и легкий для понимания код!

4

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector