4

I am 4 hours-new to C++ and have hit a brick wall with string vectors. When trying to add multiple strings to a string vector, I keep erroring out. I'd like to use push_back.

I would also like to display this string vector, but I'm not sure how (I know how to display non-vectors). Given that I have not been able to add a string to a vector of strings, I did not attempt to display the vector of strings yet.

profile.hpp

#include <iostream>
#include <vector>

class Profile 
{
private:
    std::string name;
    std::string city;
    std::string country;
    int age;
    std::vector<std::string> hobbies;

public:
    std::vector<std::string> add_hobbies(std::string new_hobbies);
};

profile.cpp

#include <iostream>
#include "profile.hpp"

Profile::Profile(std::string new_name, int new_age, std::string new_city, std::string new_country)
    : name(new_name), age(new_age), city(new_city), country(new_country) 
{}

void Profile::add_hobbies(std::string new_hobbies) 
{
    hobbies.push_back(new_hobbies);
}

app.cpp

#include <iostream>
#include "profile.hpp"
int main()
{
    Profile sam("Sam Drakkila", 30, "New York", "USA");
    sam.add_hobbies("Play golf", "Read books", "Eat tennis balls"); // This doesn't seem to work. 
}

g++ app.cpp profile.cpp. Prints a massive log of errors.

JeJo
  • 30,635
  • 6
  • 49
  • 88
  • For display the vector of strings, you could have googled it: [How to print out the contents of a vector?](https://stackoverflow.com/questions/10750057/how-to-print-out-the-contents-of-a-vector) – JeJo Aug 11 '19 at 07:40

3 Answers3

5

You have the following problems in your code:

  1. You have declared add_hobbies returns std::vector<std::string>, but in definition you have returned void. Presumably, you should have declared as a void function as it seems to be a setter function.
  2. Secondly, you are passing a number of strings instead of a single string which you defined here:

    void Profile::add_hobbies(std::string new_hobbies) //>>> as per defenition, only one string can be passed!
    //                        ^^^^^^^^^^^^^^^^^^^^^^^^
    

    If you want to pass an arbitrary number of strings, you could usestd::initializer_list<std::string> instead.

  3. Thirdly, you are missing the constructor declaration in the header file. Add in the definition of class profile.hpp

    Profile(std::string new_name, int new_age, std::string new_city, std::string new_country);
    
  4. Last but not least, you need to include the <string> header in order to use std::string(credits @πάντα ῥεῖ)

That means, (See live online)

#include <iostream>
#include <vector>
#include <string>           // std::string
#include <initializer_list> // std::initializer_list

class Profile 
{    
private:
    // ... other members
    std::vector<std::string> hobbies;

public:
    // ... other member functions
    void add_hobbies(std::initializer_list<std::string> new_hobbies)
  //^^^^             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    {
        hobbies.reserve(hobbies.size() + new_hobbies.size()); // reserve memory to avoid, unwanted reallocations
        for (const auto& hobby : new_hobbies) hobbies.emplace_back(hobby);
    }
};

int main() 
{
    Profile sam{};
    sam.add_hobbies({ "Play golf", "Read books", "Eat tennis balls" }); // now works
    //             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}

Alternatively using variadic templates and feature fold expression. (See live online)

#include <iostream>
#include <vector>
#include <string>      // std::string
#include <type_traits> // std::enable_if, std::is_same, std::common_type

using namespace std::literals;

class Profile 
{
private:
    // ... other members
    std::vector<std::string> hobbies;

public:
    // ... other member functions
    template<typename... Args> // sfinae to restrict the Args type to be only std::string s
    std::enable_if_t<std::is_same_v<std::common_type_t<Args...>, std::string>>
        add_hobbies(Args&& ... args)
    {
        hobbies.reserve(hobbies.size() + sizeof...(Args));
        (hobbies.emplace_back(std::forward<Args>(args)), ...);
    }
};

int main() 
{
    Profile sam{};
    sam.add_hobbies("Play golf"s, "Read books"s, "Eat tennis balls"s); // now works
    //             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
JeJo
  • 30,635
  • 6
  • 49
  • 88
1

You declare add_hobbies as returning a vector in your class declaration.

bipll
  • 11,747
  • 1
  • 18
  • 32
1

There are a few errors in your code:

Missing constructor declaration:

Profile(std::string new_name, int new_age, std::string new_city, std::string new_country);

Mismatch between return type of the declaration and definition of add_hobbies, should be void (since you're not returning anything).

void Profile::add_hobbies(std::string new_hobbies) { // ... } 

You're also trying to pass 3 of them, while the function only has 1 parameter:

void add_hobbies(std::string const& h1, std::string const& h2, std::string const& h3);

// ... 

void Profile::add_hobbies(std::string const& h1, std::string const& h2, std::string const& h3) {
  hobbies.push_back(h1);
  hobbies.push_back(h2);
  hobbies.push_back(h3);
}
Andreas DM
  • 10,685
  • 6
  • 35
  • 62
  • "_Passing `const char[]` instead of `std::string` to `add_hobbies`..._" This isn't an issue. `const char*` (not `[]`) in the parameter will be implicitly cast to `std::string`. Everything else seems on point. :) – TrebledJ Aug 10 '19 at 06:22
  • @TrebledJ oopsie – Andreas DM Aug 10 '19 at 06:52