Structure to string in elegant way

10,824

Solution 1

Since structs have public visibility, you can just inject a member function to the struct directly to do the trick, like this for example:

#include <iostream>
#include <string>

using namespace std;

struct movies_t {
  string title;
  int year;

  string toString()
  {
    return "title = " + title + ", year = " + to_string(year);
  }
};

int main()
{
    struct movies_t m{"Odyssey", -800};
    cout << m.toString() << endl;
}

Output:

title = Odyssey, year = -800

Solution 2

There are many ways to implement this. The one I favour is to provide an ADL free-function to_string and an overload of operator<<.

Namespace added for exposition of ADL:

#include <string>
#include <ostream>
#include <sstream>
#include <iostream>

namespace movie
{
    struct movies_t {
      std::string title;
      int year;
    };

    std::ostream& operator<<(std::ostream& os, movies_t const& arg)
    {
        os << "title = " << arg.title << ", year = " << arg.year;
    }

    std::string to_string(movies_t const& arg)
    {
        std::ostringstream ss;
        ss << arg;
        return std::move(ss).str();  // enable efficiencies in c++17
    }
}

int main()
{
    auto m = movie::movies_t { "Star Wars", 1977 };

    std::cout << m << '\n';

    using std::to_string;
    std::cout << to_string(m) << '\n';
}

Solution 3

You can make that member function const to ensure only members marked mutable are modifiable.

#include <iostream>
#include <sstream>

struct movies_t {
    std::string title;
    int year;

    std::string _to_string() const {
        std::ostringstream stream_out;
        stream_out << "title: " << title << " year: " << year;
        return stream_out.str();
    }

    std::string toString() const {
        return "title = " + title + " year = " + std::to_string(year);
    }
};

std::ostream& operator<<(std::ostream& stream_out, const movies_t& M) {
    stream_out << M.title << " " << M.year;
    return stream_out;
}

std::string _to_string(const movies_t M) {
    std::ostringstream stream_out;
    stream_out << M.title << " " << M.year;
    return stream_out.str();
}

int main() {

    movies_t N{"Friends", 1994};

    std::cout << N << std::endl;
    std::cout << _to_string(N) << std::endl;
    std::cout << N._to_string() << std::endl;
    std::cout << N.toString() << std::endl;

    return 0;
}

Solution 4

If you can't edit the struct you might want to wrap another class around

class MoviesExpansion {
public:
    MoviesExpansion(std::string title, int year) // Initialize movie in constructor
    {
        movies.title = title;
        movies.year = year;
    }

    movies_t& getMovies() { return movies; } // To get the raw movie for passing to the library.

private:
    movies_t movies; // The struct to add the additional functionality

    std::string toString() // The function we want to add
    {
        return "title = " + movies.title + " | year = " + std::to_string(movies.year);
    }
}

then you can do

int main()
{
    MoviesExpansion myMovies("Movie Title", 2018); // Create MoviesExpansion containing an movies_t structure

    std::cout << myMovies.toString(); // Outputs "title = Movie Title | year = 2018"

    someCompiledLibraryFunction(myMovies.getMovies()); //Call lib function

    myMovies.getMovies().title = "New Title"; // Change Movie Title

    std::cout << myMovies.toString(); // Outputs "title = New Title | year = 2018"

   return 1;

}
Share:
10,824

Related videos on Youtube

vico
Author by

vico

Updated on September 15, 2022

Comments

  • vico
    vico over 1 year

    I have structure:

    struct movies_t {
      string title;
      int year;
    } 
    

    I would like this structure to have behavior to show it's fields in string.

    std:string toString()
    {
    return "title=" title + "year="+ itostr(year);
    }
    

    I can't change struct to class since I should pass it to compiled library which code is unknown. What is the best way to implement this?

    • UnholySheep
      UnholySheep about 6 years
      Show its fields in string where? For ostream like objects you can just overload operator<<
    • Some programmer dude
      Some programmer dude about 6 years
      In C++ the only different between a struct and a class is the default visibility (public for struct, private for class). That's it. So nothing stops you from making a member function.
    • default
      default about 6 years
      what's wrong with the function you have now?
    • Daniel H
      Daniel H about 6 years
      Your suggested toString function would produce something like "title=Harry Potter and the Philosopher's Stoneyear=1998", which is probably not the format you want.