1

I'm trying to make something similar to std::Map. I have two classes, NameValue which takes a name and a Value. The class Value can hold data of type int and string. I want the Value class to also accept NameValue to be able to create nested objects. Currently the boost::variant is used to hold the data types allowed to be used.

NameValue.h

  #ifndef INC_NAME_VALUE_H_
    #define INC_NAME_VALUE_H_

    #include <boost/variant.hpp>
    #include <iostream>
    #include <string>
    #include "value.h"

    namespace config {

    using namespace std;
    class Value;  // forward declaration
    class NameValue {
     private:
      string name;
      Value* valuePtr;

     public:
      NameValue(){};
      NameValue(string name, Value& value)
          : name(name)
          , valuePtr(&value){};

      void Print() {
        cout << name << " : ";
        // valuePtr->Print();
      }

      void Set(Value* value) { valuePtr = value; }
    };
    }

    #endif /* INC_NAME_VALUE_H_ */

Value.h

    #ifndef INC_VALUE_H_
#define INC_VALUE_H_

#include <boost/variant.hpp>
#include <iostream>
#include <string>
#include "name_value.h"

namespace config {
using namespace std;

using variantDataType = boost::variant<int, string>;

class Value {
 private:
  variantDataType value;

 public:
  Value(){};
  Value(variantDataType const& value)
      : value(value){};
  void Print() { cout << value << endl; }
};
}
#endif /* INC_VALUE_H_ */

In Value.h I want to add NameValue to variant like this:

boost::variant<int,string,NameValue> value;

main.cpp

Value i(42);
NameValue nv("meaning", i);
NameValue nv2("nested, NameValue("deep", "value"));//this is what I want

Maybe I'm on the wrong track using variant or the way I'm using dependencies. If there is some other way to make it work I would appreciate the suggestions.

  • you can't have a recursive type without some indirection – Tyker Jun 27 '18 at 13:11
  • 1
    You use forward declarations which is good. But you don't really remove the source of the circular dependency: The actual `#include "value.h"`. Remove that, and define the functions using the pointer in a source file instead of inline in the class. – Some programmer dude Jun 27 '18 at 13:12
  • Unrelated to your problem, but please read [Why is “using namespace std” considered bad practice?](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) and [using namespace std; in a header file](https://stackoverflow.com/questions/14575799/using-namespace-std-in-a-header-file) (which makes the first issue worse). – Some programmer dude Jun 27 '18 at 13:13
  • Thank you @Someprogrammerdude for your helpful advice! With `code` void NameValue::Set(NameValue* nameValue) { valuePtr = nameValue; } `code` I get "cannot convert 'config::NameValue*' to 'config::Value*' in assignment". Is it possible to make the Value class to accept NameValue objects? Is polymorphism needed? – user3192107 Jun 28 '18 at 09:27
  • I figured it out with `valuePtr = (Value*)&nameValue;` – user3192107 Jun 28 '18 at 09:53

0 Answers0