本文介绍了模板推导功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一些接受 std :: basic_string 或char数组的模板化函数, basic_string

I am trying to write some templated functions that accept either a std::basic_string or a char array from which the basic_string could be constructed.

我当前的解决方案是:

#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" });
}

但这意味着对于每个函数,我必须编写另一个调用该函数的函数第一。真烦人;有更简单的方法吗?也许它可能是模板推论指南,但据我所知,对于函数,仅类是不存在的。

But this means that for each function I have to write another function that calls the first one. That's pretty annoying; is there an easier way to do it? Maybe it could be a template deduction guide, but as far as I know it does not exist for functions, only classes.

第一个模板函数不足,因为模板推导失败:编译器无法从 CharT推导 std :: basic_string< CharT> 中的 CharT const * 。这就是为什么我需要一种更简单的方法告诉编译器的原因。

The first templated function is not sufficient because the template deduction fails: the compiler cannot deduce CharT in std::basic_string<CharT> from CharT const *. That is why I need a simpler way to tell this to the compiler.

推荐答案

经过更多研究之后,最好的选择是imo将使用C ++ 17功能 std :: basic_string_view

After a bit more of research, the best option imo is to use the C++17 feature 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
}

因此,如果您可以使用C ++ 17编译器,请忽略下面的较早解释。

So forget about the older explanation below if you have access to a C++17-compiler.

这里有两种情况需要考虑。 第一种情况是,您实际上并不希望对基本字符串做一些特殊的事情,而是只应用对 char 也可用的方法。 -array(并且只想确保正确调用它,而不管参数如何)。在这种情况下,我只使用一个通用的模板参数:

There are two cases here to consider. The first case is that you do not really want to do something special with the basic string, but rather you apply only methods also available for the char-array (and just want to make sure it's called correctly regardless of the parameters). In this case, I'd simply use a general template parameter:

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 类尝试做的事情(但仍需要进行一些改进,只需对其进行操作即可):

Second case is that you really want to do some special operation on the string which is not present for the char array. In this case you need an overload for basic_string, but you probably want to write it only once and not for each and every function you use. This is what the following string_invoker class tries to do (but it still needs some improvement, just working on it):

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" });
}

这篇关于模板推导功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 05:40