Home > OS >  c string template no matching function for call to basic_string<char>
c string template no matching function for call to basic_string<char>

Time:01-04

I am writing common function to convert type T to string:

  1. when T is numeric type just use std::to_string

  2. when others use stringstream operator <<

  3. when T is std::string just return T

template <typename Numeric>
string to_str1(Numeric n){
    return std::to_string(n);
}

template <typename NonNumeric>
std::string to_str2(const NonNumeric& v){
    std::stringstream ss;
    ss << v;
    return ss.str();
}

// if T is string just return
std::string to_str2(const std::string& v){
    return v;
}

template<typename T>
string to_str(const T& t){
    if(std::is_integral<T>::value){
        return to_str1(t);
    }else{
        return to_str2(t);
    }
}

test usage:

int a = 1101;
cout << to_str(a) << endl;

string s = "abc";
cout << to_str(s) << endl;  // should use to_str2(const std::string& v),but compile error

but compile error:

In instantiation of string to_str1 ..... no matching function for call to to_string(std::__cxx11::basic_string

I don't know why this error, ?

CodePudding user response:

When you write

if(std::is_integral<T>::value){
    return to_str1(t);
}else{
    return to_str2(t);
}

Then it is true that the if condition is either always true or always false at runtime, but it is still required that the two branches can be compiled. The first branch however doesn't work with T = std::string.

If you want to exclude branches from being compiled completely (aside from syntax check) based on a compile time constant, then you can use if constexpr:

if constexpr(std::is_integral<T>::value){
    return to_str1(t);
}else{
    return to_str2(t);
}

This tells the compiler to check the if condition at compile-time and only compile the branch that would be taken.

This requires C 17 or later.

CodePudding user response:

The problem is that both the if and else branch will be evaluated at compile-time; you can use Constexpr If (since C 17).

If the value is true, then statement-false is discarded (if present), otherwise, statement-true is discarded.

template<typename T>
string to_str(const T& t){
    if constexpr (std::is_integral<T>::value){
        return to_str1(t);
    }else{
        return to_str2(t);
    }
}

Or overload to_str with the help of SFINAE.

// for integral-numbers
template <typename T>
typename std::enable_if<std::is_integral<T>::value, std::string>::type
to_str(T n){
    return std::to_string(n);
}

// for non-integral-numbers
template <typename T>
typename std::enable_if<!std::is_integral<T>::value, std::string>::type
to_str(const T& v){
    std::stringstream ss;
    ss << v;
    return ss.str();
}

// if T is string just return
std::string to_str(const std::string& v) {
    return v;
}
  •  Tags:  
  • Related