0

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, ?

1
  • You need if constexpr instead of if, since the latter will validate both branches even if the condition is known at compile-time. Commented Jan 3, 2022 at 13:40

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.