1

I want to check if a given variable is a char. Right now, my function returns a string based on the elements of a vector.

The issue is if I give it a char vector, then to_string() gives me the numeric value of the character 'foo'. So where I want it to read:

a b

it instead reads

97 98

I would rather implement something into the function than create an overload, since I have two other overloads already for argument types vector<vector<T>> and vector<array<T, 2>> that need to run by the same logic and it would be messy to have six total functions rather than three.

   /** to string for vector that has singular elements
     * vtos : vector to string
     **/
    template <class T>
    basic_string<char> vtos (vector<T> &v )
    {
        string ret;
        int i = 0;
    
        for ( T& foo: v )
        {
            ret.append(to_string(foo) + " ");
            if (++i % 10 ==0)
                ret.push_back('\n');
        }
    
        return ret;
    }

++++++++++++++++++++++++++++++++++

EDIT: You can use the marked solution if you have C++17. I don't, so I decided to just use a default parameter.

EDIT 2: The marked answer now also includes an edit, check there for a pre-c++17 answer. Will leave my own here too.

template <class T>
basic_string<char> vtos (vector<T> &v, bool isChar=false)
{
    string ret;
    int i = 0;

    for ( T& foo: v )
    {
        if (isChar)
            ret.push_back(foo);
        else
            ret.append(to_string(foo));

        ret.push_back(' ');

        if (++i % 10 ==0)
            ret.push_back('\n');
    }

    return ret;
}
  • `basic_string` is just `string` BTW. – Passer By Oct 04 '20 at 08:35
  • 1
    `if constexpr (std::is_same_v) ...` ? Or add `my_to_string` with an overload for `char`. – Evg Oct 04 '20 at 08:42
  • I don't have C++17 installed, can't use that solution. Decided instead to simply add a default bool parameter isChar, since I only need to know one specific case. Thanks you guys for the answers – Micah Johnson Oct 04 '20 at 09:06
  • I have update my post to include a c++14 solution. It can be used in c++11 too if you replace `is_same_v<>` by `is_same<>::value` – Martin Morterol Oct 04 '20 at 11:13

1 Answers1

2

You can try with an if constexpr and the type traits is_same

#include <iostream>
#include <type_traits>
#include <vector>


template <class T>
std::string vtos (const std::vector<T> &v )
{
    std::string ret;
    int i = 0;
    auto to_string = [](const auto& elem)
    {
       if constexpr ( std::is_same_v<T,char> )
       {
           return std::string(1,elem);
       }
       else
       {
          return std::to_string(elem);   
       }
    };
    for (const T& foo: v )
    {
        ret.append(to_string(foo) + " ");
        if (++i % 10 ==0) ret.push_back('\n');
    }
    return ret;
}
int main()
{
   std::cout << vtos(std::vector<char>{'a','b'});
}

Note:


C++14: you can replace if constexpr with SFINAE. Demo

#include <iostream>
#include <type_traits>
#include <vector>

template <class T> 
std::enable_if_t<std::is_same_v<T,char>, std::string>  to_string(const T& elem)
{
    return std::string(1,elem); 
}

template <class T> 
std::enable_if_t<not std::is_same_v<T,char>, std::string> to_string(const T& elem)
{
    return std::to_string(elem); 
}

template <class T>
std::string vtos (const std::vector<T> &v )
{
    std::string ret;
    int i = 0;
    for (const T& foo: v )
    {
        ret.append(to_string(foo) + " ");
        if (++i % 10 ==0) ret.push_back('\n');
    }
    return ret;
}
int main()
{
   std::cout << vtos(std::vector<char>{'a','b'});
   std::cout << vtos(std::vector<int>{12,5});
}

Edit : Evg was faster, if you post an answer I will delete this

Martin Morterol
  • 2,560
  • 1
  • 10
  • 15