type deduction from char array to std::string

你离开我真会死。 提交于 2019-12-08 04:11:15

问题


I'm trying to write sum function using variadic template. In the code I would write something like

sum(1, 2., 3)

and it will return most general type of the sum (in this case - double). The problem is with characters. When I call it like

sum("Hello", " ", "World!") 

template parameters are deduces as const char [7] for example, thus it won't compile. I found the way to specify last argument as std::string("World!"), but it's not pretty, is there any way to achieve automatic type deduction to std::string or correctly overload sum?

The code I have so far:

template<typename T1, typename T2>
auto sum(const T1& t1, const T2& t2) {
    return t1 + t2;
}

template<typename T1, typename... T2>
auto sum(const T1& t1, const T2&... t2) {
    return t1 + sum(t2...);
}

int main(int argc, char** argv) {
    auto s1 = sum(1, 2, 3);
    std::cout << typeid(s1).name() << " " << s1 << std::endl;

    auto s2 = sum(1, 2.0, 3);
    std::cout << typeid(s2).name() << " " << s2 << std::endl;

    auto s3 = sum("Hello", " ", std::string("World!"));
    std::cout << typeid(s3).name() << " " << s3 << std::endl;

    /* Won't compile! */
    /*
    auto s4 = sum("Hello", " ", "World!");
    std::cout << typeid(s4).name() << " " << s4 << std::endl;
    */

    return 0;
}

Output:

i 6
d 6
Ss Hello World!

回答1:


I would just write a simple overloaded identity function which handles const char* specially.

template<typename T>
decltype(auto) fix(T&& val)
{
    return std::forward<T>(val);
} 

auto fix(char const* str)
{
    return std::string(str);
}

template<typename T1, typename T2>
auto sum(const T1& t1, const T2& t2) {
    return fix(t1) + t2;
}

template<typename T1, typename... T2>
auto sum(const T1& t1, const T2&... t2) {
    return t1 + sum(t2...);
}



回答2:


Ultimately you're char pointer types don't deal well with being on both the left and right side of operator +.` You can overload to manufacture an intermediary if desired.

Below I took liberty to refactor this down to a single-param-supported sum (not a required step, but allows sum(x) overloads, which are clearer to understand). Hopefully you get the idea.

#include <iostream>
#include <string>

// generic identity
template<typename T1>
auto sum(const T1& t1)
{
    std::cout << __PRETTY_FUNCTION__ << '\n';
    return t1;
}

// specialized for const char [N]
auto sum(const char *s)
{
    std::cout << __PRETTY_FUNCTION__ << '\n';
    return std::string(s);
}

template<typename T1, typename... T2>
auto sum(const T1& t1, const T2&... t2)
{
    std::cout << __PRETTY_FUNCTION__ << '\n';
    return t1 + sum(t2...);
}

int main(int argc, char** argv) {

    std::cout << sum(1,2,3) << '\n';
    std::cout << sum(1, 2.0, 3) << '\n';
    std::cout << sum("Hello", " ", std::string("World!")) << '\n';
    std::cout << sum("Hello", " ", "World!");
    return 0;
}

Output

auto sum(const T1 &, const T2 &...) [T1 = int, T2 = <int, int>]
auto sum(const T1 &, const T2 &...) [T1 = int, T2 = <int>]
auto sum(const T1 &) [T1 = int]
6
auto sum(const T1 &, const T2 &...) [T1 = int, T2 = <double, int>]
auto sum(const T1 &, const T2 &...) [T1 = double, T2 = <int>]
auto sum(const T1 &) [T1 = int]
6
auto sum(const T1 &, const T2 &...) [T1 = char [6], T2 = <char [2], std::__1::basic_string<char>>]
auto sum(const T1 &, const T2 &...) [T1 = char [2], T2 = <std::__1::basic_string<char>>]
auto sum(const T1 &) [T1 = std::__1::basic_string<char>]
Hello World!
auto sum(const T1 &, const T2 &...) [T1 = char [6], T2 = <char [2], char [7]>]
auto sum(const T1 &, const T2 &...) [T1 = char [2], T2 = <char [7]>]
auto sum(const char *)
Hello World!

Best of luck



来源:https://stackoverflow.com/questions/30083662/type-deduction-from-char-array-to-stdstring

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!