0

I am new in c++ I need to hold any variable in std::map. I have to use -std=c++11 standard, no boost library. Unfortunatelly as I have found out there is necessary auxiliary class.

I created desing of class - var.hpp:

class ValueBase {

    public:

        ValueBase();
        ~ValueBase(){};

};


template<typename T>
class Value : public ValueBase {

    private:
        T mValue;

    public:

        Value(T value); 
        T getValue();

};

and implementation - var.cpp:

template<typename T>
Value<T>::Value(T value) {
    this->mValue = value;
}

template<typename T>
T Value<T>::getValue() {
    return this->mValue;
}

Finally example of use:

#include <map>
#include <string>

#include "var.hpp"

int main() {

    std::map<std::string, ValueBase *> vars;

    ValueBase *value = new Value<int>(5);
    vars.insert(std::pair<std::string, ValueBase *>("key", value));

    for(const auto &element : vars) {
        delete vars[element.first];
    }

    return 0;

}

Compilation error:

Undefined symbols for architecture x86_64:
  "ValueBase::ValueBase()", referenced from:
      Value<int>::Value(int) in test-c8ef7e.o
  "std::logic_error::logic_error(char const*)", referenced from:
      std::length_error::length_error(char const*) in test-c8ef7e.o
  "std::length_error::~length_error()", referenced from:
      std::__1::__throw_length_error(char const*) in test-c8ef7e.o
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__init(char const*, unsigned long)", referenced from:
      std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string<std::__1::nullptr_t>(char const*) in test-c8ef7e.o
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
      std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>::pair(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, ValueBase* const&) in test-c8ef7e.o
      std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, ValueBase*>::pair(std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, ValueBase*> const&) in test-c8ef7e.o
      std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, ValueBase*>::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>(std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*> const&) in test-c8ef7e.o
      void std::__1::allocator_traits<std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, void*> > >::__construct<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::integral_constant<bool, false>, std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, void*> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in test-c8ef7e.o
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()", referenced from:
      _main in test-c8ef7e.o
      std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, ValueBase*>::~pair() in test-c8ef7e.o
      std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>::~pair() in test-c8ef7e.o
      void std::__1::allocator_traits<std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, void*> > >::__destroy<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const>(std::__1::integral_constant<bool, false>, std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, void*> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const*) in test-c8ef7e.o
  "std::terminate()", referenced from:
      ___clang_call_terminate in test-c8ef7e.o
  "typeinfo for std::length_error", referenced from:
      std::__1::__throw_length_error(char const*) in test-c8ef7e.o
  "vtable for std::length_error", referenced from:
      std::length_error::length_error(char const*) in test-c8ef7e.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
  "operator delete(void*)", referenced from:
      _main in test-c8ef7e.o
      std::__1::_DeallocateCaller::__do_call(void*) in test-c8ef7e.o
  "operator new(unsigned long)", referenced from:
      _main in test-c8ef7e.o
      std::__1::__libcpp_allocate(unsigned long, unsigned long) in test-c8ef7e.o
  "___cxa_allocate_exception", referenced from:
      std::__1::__throw_length_error(char const*) in test-c8ef7e.o
  "___cxa_begin_catch", referenced from:
      ___clang_call_terminate in test-c8ef7e.o
  "___cxa_call_unexpected", referenced from:
      std::__1::__tree<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, std::__1::__map_value_compare<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, true>, std::__1::allocator<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*> > >::destroy(std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, void*>*) in test-c8ef7e.o
      std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, void*> >::deallocate(std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, void*>*, unsigned long) in test-c8ef7e.o
      std::__1::__tree<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, std::__1::__map_value_compare<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, true>, std::__1::allocator<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*> > >::__insert_node_at(std::__1::__tree_end_node<std::__1::__tree_node_base<void*>*>*, std::__1::__tree_node_base<void*>*&, std::__1::__tree_node_base<void*>*) in test-c8ef7e.o
      std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::compare(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const in test-c8ef7e.o
      std::__1::char_traits<char>::compare(char const*, char const*, unsigned long) in test-c8ef7e.o
      std::__1::unique_ptr<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, void*>, std::__1::__tree_node_destructor<std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, void*> > > >::unique_ptr<true, void>(std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, void*>*, std::__1::__dependent_type<std::__1::__unique_ptr_deleter_sfinae<std::__1::__tree_node_destructor<std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, void*> > > >, true>::__good_rval_ref_type) in test-c8ef7e.o
      std::__1::unique_ptr<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, void*>, std::__1::__tree_node_destructor<std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, void*> > > >::unique_ptr(std::__1::unique_ptr<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, void*>, std::__1::__tree_node_destructor<std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, void*> > > >&&) in test-c8ef7e.o
      ...
  "___cxa_free_exception", referenced from:
      std::__1::__throw_length_error(char const*) in test-c8ef7e.o
  "___cxa_throw", referenced from:
      std::__1::__throw_length_error(char const*) in test-c8ef7e.o
  "___gxx_personality_v0", referenced from:
      _main in test-c8ef7e.o
      std::__1::__tree<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, std::__1::__map_value_compare<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, true>, std::__1::allocator<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*> > >::destroy(std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, void*>*) in test-c8ef7e.o
      std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, void*> >::deallocate(std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, void*>*, unsigned long) in test-c8ef7e.o
      std::__1::__tree<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, std::__1::__map_value_compare<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, true>, std::__1::allocator<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*> > >::__construct_node(std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, ValueBase*> const&) in test-c8ef7e.o
      std::__1::__tree<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, std::__1::__map_value_compare<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*>, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, true>, std::__1::allocator<std::__1::__value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, ValueBase*> > >::__insert_node_at(std::__1::__tree_end_node<std::__1::__tree_node_base<void*>*>*, std::__1::__tree_node_base<void*>*&, std::__1::__tree_node_base<void*>*) in test-c8ef7e.o
      std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::compare(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const in test-c8ef7e.o
      std::__1::char_traits<char>::compare(char const*, char const*, unsigned long) in test-c8ef7e.o
      ...
ld: symbol(s) not found for architecture x86_64

I found similar solutions what doesn't work for me. Here and here. Thank you for your help and especially for you explanation :). Thank you.

Amateur
  • 43
  • 6
  • I recently answered a similar question, you may be interested in my implementation: https://stackoverflow.com/a/63743699/4641116 – Eljay Sep 10 '20 at 16:53
  • Where have you defined (implemented) the `ValueBase` constructor and destructor? – Some programmer dude Sep 10 '20 at 16:55
  • 1
    And you probably want to check out [`std::any`](https://en.cppreference.com/w/cpp/utility/any) (or [Boost any](https://www.boost.org/doc/libs/1_74_0/doc/html/any.html)). – Some programmer dude Sep 10 '20 at 16:56
  • Lastly, how *exactly* are you building the program? What command are you using? What does the full command-line look like? – Some programmer dude Sep 10 '20 at 16:58
  • *"implementation - var.cpp"*. see [why-can-templates-only-be-implemented-in-the-header-file](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – Jarod42 Sep 10 '20 at 17:02
  • `delete vars[element.first];` could simply be `delete element.second`, and you need virtual destructor for your base class. – Jarod42 Sep 10 '20 at 17:03

0 Answers0