Can I have std::vector store these subclasses mixed?

Discussion in 'C++' started by Eric Lilja, Feb 26, 2005.

  1. Eric Lilja

    Eric Lilja Guest

    Hello, in my program I am reading a text file that has format:
    option=value
    There are several types of options and they expect values of different types
    (mostly strings or integers). I made a templated base class Option and had
    my different options derive from Option instantiated for their type (i.e.,
    class LongOption inherits publicly from Option<long>). I selected this
    approach because I wanted a uniform interface for obtaining the type and
    value of a given option. I came up with the following class tree for testing
    purposes:
    template <typename T>
    class Option
    {
    public:
    enum OptionType
    {
    LONG,
    STRING
    };

    Option(const std::string& name)
    :
    m_name(name),
    m_not_set(true) {}

    virtual ~Option() {}

    T get_value() const
    {
    if(m_not_set)
    throw;

    return m_value;
    }

    void set_value(const T& value)
    {
    m_not_set = false;

    m_value = value;
    }

    virtual OptionType get_type() const = 0;

    private:
    std::string m_name;
    bool m_not_set;
    T m_value;
    };

    class LongOption : public Option<long>
    {
    public:
    LongOption(const std::string& name)
    :
    Option<long>(name) {}

    virtual OptionType get_type() const
    {
    return STRING;
    }
    };

    class StringOption : public Option<std::string>
    {
    public:
    StringOption(const std::string& name)
    :
    Option<std::string>(name) {}

    virtual OptionType get_type() const
    {
    return LONG;
    }
    };

    That seems to compile, but I cannot do:
    std::vector<Option*> options(11);
    options[0] = new StringOption("Name=");
    The compiler complains:
    $ make gccmain
    g++ gccmain.cpp -o gccmain
    gccmain.cpp: In function `int main()':
    gccmain.cpp:6: error: use of class template `template<class T> class Option'
    as expression
    gccmain.cpp:6: error: parse error before `>' token
    gccmain.cpp:8: error: `options' undeclared (first use this function)
    gccmain.cpp:8: error: (Each undeclared identifier is reported only once for
    each function it appears in.)
    make: *** [gccmain] Error 1

    Not being able to store my different options in the same container makes
    reading the file with options a lot messier...are their any ways to solve
    this? I'm not very good at templates so I've certainly made a number of
    silly mistakes.

    / Eric
    Eric Lilja, Feb 26, 2005
    #1
    1. Advertising

  2. Eric Lilja

    Rolf Magnus Guest

    Eric Lilja wrote:

    > Hello, in my program I am reading a text file that has format:
    > option=value
    > There are several types of options and they expect values of different
    > types (mostly strings or integers). I made a templated base class Option
    > and had my different options derive from Option instantiated for their
    > type (i.e., class LongOption inherits publicly from Option<long>). I
    > selected this approach because I wanted a uniform interface for obtaining
    > the type and value of a given option. I came up with the following class
    > tree for testing purposes:
    > template <typename T>
    > class Option
    > {
    > public:
    > enum OptionType
    > {
    > LONG,
    > STRING
    > };


    This enum must be changed whenever you add another derived type. I'd use
    typeinfo instead.

    >
    > Option(const std::string& name)
    > :
    > m_name(name),
    > m_not_set(true) {}
    >
    > virtual ~Option() {}
    >
    > T get_value() const
    > {
    > if(m_not_set)
    > throw;


    throw what?

    >
    > return m_value;
    > }
    >
    > void set_value(const T& value)
    > {
    > m_not_set = false;
    >
    > m_value = value;
    > }
    >
    > virtual OptionType get_type() const = 0;
    >
    > private:
    > std::string m_name;
    > bool m_not_set;
    > T m_value;
    > };
    >
    > class LongOption : public Option<long>
    > {
    > public:
    > LongOption(const std::string& name)
    > :
    > Option<long>(name) {}
    >
    > virtual OptionType get_type() const
    > {
    > return STRING;
    > }
    > };


    I don't really think you need to derive for each type if you use typeinfo.
    I'll present an example of what I mean below.

    >
    > class StringOption : public Option<std::string>
    > {
    > public:
    > StringOption(const std::string& name)
    > :
    > Option<std::string>(name) {}
    >
    > virtual OptionType get_type() const
    > {
    > return LONG;
    > }
    > };
    >
    > That seems to compile, but I cannot do:
    > std::vector<Option*> options(11);


    Option is a template, not a type. Therefore, you cannot create a vector of
    Option pointers.

    > options[0] = new StringOption("Name=");
    > The compiler complains:
    > $ make gccmain
    > g++ gccmain.cpp -o gccmain
    > gccmain.cpp: In function `int main()':
    > gccmain.cpp:6: error: use of class template `template<class T> class
    > Option' as expression
    > gccmain.cpp:6: error: parse error before `>' token
    > gccmain.cpp:8: error: `options' undeclared (first use this function)
    > gccmain.cpp:8: error: (Each undeclared identifier is reported only once
    > for
    > each function it appears in.)
    > make: *** [gccmain] Error 1
    >
    > Not being able to store my different options in the same container makes
    > reading the file with options a lot messier...are their any ways to solve
    > this?


    Yes. Make a non-templated base class and derive your Option template from
    it. Then store pointers to that base class in your container.

    > I'm not very good at templates so I've certainly made a number of
    > silly mistakes.



    class OptionBase
    {
    public:
    OptionBase(const std::string& name)
    : m_name(name),
    m_not_set(true)
    {
    }
    virtual std::typeinfo get_type() const = 0;
    virtual ~OptionBase() {}

    private:
    std::string m_name;
    bool m_not_set;
    };

    template <typename T>
    class Option : public OptionBase
    {
    public:
    Option(const std::string& name)
    : OptionBase(name)
    {}

    T get_value() const
    {
    if(m_not_set)
    throw SomeException();

    return m_value;
    }

    void set_value(const T& value)
    {
    m_not_set = false;

    m_value = value;
    }

    virtual std::typeinfo get_type() const
    {
    return typeid(T);
    }

    private:
    T m_value;
    };

    //Don't need to derive for each type anymore - a typedef is sufficient
    typedef Option<Long> LongOption;
    typedef Option<std::string> StringOption;

    //...
    std::vector<OptionBase*> options(11);
    options[0] = new StringOption("Name=");

    //And to test for the type:
    if (options[0]->get_type() == typeid(std::string))
    {
    //we have a string
    }

    Another thing you might be interested in is boost::any. See
    http://www.boost.org/doc/html/any.html
    Rolf Magnus, Feb 26, 2005
    #2
    1. Advertising

  3. Eric Lilja

    Eric Lilja Guest

    "Rolf Magnus" <> wrote in message
    news:cvpjvl$jrl$00$-online.com...
    > Eric Lilja wrote:
    >
    >> Hello, in my program I am reading a text file that has format:
    >> option=value
    >> There are several types of options and they expect values of different
    >> types (mostly strings or integers). I made a templated base class Option
    >> and had my different options derive from Option instantiated for their
    >> type (i.e., class LongOption inherits publicly from Option<long>). I
    >> selected this approach because I wanted a uniform interface for obtaining
    >> the type and value of a given option. I came up with the following class
    >> tree for testing purposes:
    >> template <typename T>
    >> class Option
    >> {
    >> public:
    >> enum OptionType
    >> {
    >> LONG,
    >> STRING
    >> };

    >
    > This enum must be changed whenever you add another derived type. I'd use
    > typeinfo instead.
    >
    >>
    >> Option(const std::string& name)
    >> :
    >> m_name(name),
    >> m_not_set(true) {}
    >>
    >> virtual ~Option() {}
    >>
    >> T get_value() const
    >> {
    >> if(m_not_set)
    >> throw;

    >
    > throw what?
    >
    >>
    >> return m_value;
    >> }
    >>
    >> void set_value(const T& value)
    >> {
    >> m_not_set = false;
    >>
    >> m_value = value;
    >> }
    >>
    >> virtual OptionType get_type() const = 0;
    >>
    >> private:
    >> std::string m_name;
    >> bool m_not_set;
    >> T m_value;
    >> };
    >>
    >> class LongOption : public Option<long>
    >> {
    >> public:
    >> LongOption(const std::string& name)
    >> :
    >> Option<long>(name) {}
    >>
    >> virtual OptionType get_type() const
    >> {
    >> return STRING;
    >> }
    >> };

    >
    > I don't really think you need to derive for each type if you use typeinfo.
    > I'll present an example of what I mean below.
    >
    >>
    >> class StringOption : public Option<std::string>
    >> {
    >> public:
    >> StringOption(const std::string& name)
    >> :
    >> Option<std::string>(name) {}
    >>
    >> virtual OptionType get_type() const
    >> {
    >> return LONG;
    >> }
    >> };
    >>
    >> That seems to compile, but I cannot do:
    >> std::vector<Option*> options(11);

    >
    > Option is a template, not a type. Therefore, you cannot create a vector of
    > Option pointers.
    >
    >> options[0] = new StringOption("Name=");
    >> The compiler complains:
    >> $ make gccmain
    >> g++ gccmain.cpp -o gccmain
    >> gccmain.cpp: In function `int main()':
    >> gccmain.cpp:6: error: use of class template `template<class T> class
    >> Option' as expression
    >> gccmain.cpp:6: error: parse error before `>' token
    >> gccmain.cpp:8: error: `options' undeclared (first use this function)
    >> gccmain.cpp:8: error: (Each undeclared identifier is reported only once
    >> for
    >> each function it appears in.)
    >> make: *** [gccmain] Error 1
    >>
    >> Not being able to store my different options in the same container makes
    >> reading the file with options a lot messier...are their any ways to solve
    >> this?

    >
    > Yes. Make a non-templated base class and derive your Option template from
    > it. Then store pointers to that base class in your container.
    >
    >> I'm not very good at templates so I've certainly made a number of
    >> silly mistakes.

    >
    >
    > class OptionBase
    > {
    > public:
    > OptionBase(const std::string& name)
    > : m_name(name),
    > m_not_set(true)
    > {
    > }
    > virtual std::typeinfo get_type() const = 0;
    > virtual ~OptionBase() {}
    >
    > private:
    > std::string m_name;
    > bool m_not_set;
    > };
    >
    > template <typename T>
    > class Option : public OptionBase
    > {
    > public:
    > Option(const std::string& name)
    > : OptionBase(name)
    > {}
    >
    > T get_value() const
    > {
    > if(m_not_set)
    > throw SomeException();
    >
    > return m_value;
    > }
    >
    > void set_value(const T& value)
    > {
    > m_not_set = false;
    >
    > m_value = value;
    > }
    >
    > virtual std::typeinfo get_type() const
    > {
    > return typeid(T);
    > }
    >
    > private:
    > T m_value;
    > };
    >
    > //Don't need to derive for each type anymore - a typedef is sufficient
    > typedef Option<Long> LongOption;
    > typedef Option<std::string> StringOption;
    >
    > //...
    > std::vector<OptionBase*> options(11);
    > options[0] = new StringOption("Name=");
    >
    > //And to test for the type:
    > if (options[0]->get_type() == typeid(std::string))
    > {
    > //we have a string
    > }
    >
    > Another thing you might be interested in is boost::any. See
    > http://www.boost.org/doc/html/any.html
    >


    Very nice, Rolf! I will try out your code as soon as I've showered & shaved,
    looks real nice! Thank you for such a detailed response.

    / Eric
    Eric Lilja, Feb 26, 2005
    #3
  4. Eric Lilja

    Eric Lilja Guest

    "Eric Lilja" <> wrote in message
    news:cvplt7$240$...
    >
    > "Rolf Magnus" <> wrote in message
    > news:cvpjvl$jrl$00$-online.com...
    >> Eric Lilja wrote:
    >>
    >>> Hello, in my program I am reading a text file that has format:
    >>> option=value
    >>> There are several types of options and they expect values of different
    >>> types (mostly strings or integers). I made a templated base class Option
    >>> and had my different options derive from Option instantiated for their
    >>> type (i.e., class LongOption inherits publicly from Option<long>). I
    >>> selected this approach because I wanted a uniform interface for
    >>> obtaining
    >>> the type and value of a given option. I came up with the following class
    >>> tree for testing purposes:
    >>> template <typename T>
    >>> class Option
    >>> {
    >>> public:
    >>> enum OptionType
    >>> {
    >>> LONG,
    >>> STRING
    >>> };

    >>
    >> This enum must be changed whenever you add another derived type. I'd use
    >> typeinfo instead.
    >>
    >>>
    >>> Option(const std::string& name)
    >>> :
    >>> m_name(name),
    >>> m_not_set(true) {}
    >>>
    >>> virtual ~Option() {}
    >>>
    >>> T get_value() const
    >>> {
    >>> if(m_not_set)
    >>> throw;

    >>
    >> throw what?
    >>
    >>>
    >>> return m_value;
    >>> }
    >>>
    >>> void set_value(const T& value)
    >>> {
    >>> m_not_set = false;
    >>>
    >>> m_value = value;
    >>> }
    >>>
    >>> virtual OptionType get_type() const = 0;
    >>>
    >>> private:
    >>> std::string m_name;
    >>> bool m_not_set;
    >>> T m_value;
    >>> };
    >>>
    >>> class LongOption : public Option<long>
    >>> {
    >>> public:
    >>> LongOption(const std::string& name)
    >>> :
    >>> Option<long>(name) {}
    >>>
    >>> virtual OptionType get_type() const
    >>> {
    >>> return STRING;
    >>> }
    >>> };

    >>
    >> I don't really think you need to derive for each type if you use
    >> typeinfo.
    >> I'll present an example of what I mean below.
    >>
    >>>
    >>> class StringOption : public Option<std::string>
    >>> {
    >>> public:
    >>> StringOption(const std::string& name)
    >>> :
    >>> Option<std::string>(name) {}
    >>>
    >>> virtual OptionType get_type() const
    >>> {
    >>> return LONG;
    >>> }
    >>> };
    >>>
    >>> That seems to compile, but I cannot do:
    >>> std::vector<Option*> options(11);

    >>
    >> Option is a template, not a type. Therefore, you cannot create a vector
    >> of
    >> Option pointers.
    >>
    >>> options[0] = new StringOption("Name=");
    >>> The compiler complains:
    >>> $ make gccmain
    >>> g++ gccmain.cpp -o gccmain
    >>> gccmain.cpp: In function `int main()':
    >>> gccmain.cpp:6: error: use of class template `template<class T> class
    >>> Option' as expression
    >>> gccmain.cpp:6: error: parse error before `>' token
    >>> gccmain.cpp:8: error: `options' undeclared (first use this function)
    >>> gccmain.cpp:8: error: (Each undeclared identifier is reported only once
    >>> for
    >>> each function it appears in.)
    >>> make: *** [gccmain] Error 1
    >>>
    >>> Not being able to store my different options in the same container makes
    >>> reading the file with options a lot messier...are their any ways to
    >>> solve
    >>> this?

    >>
    >> Yes. Make a non-templated base class and derive your Option template from
    >> it. Then store pointers to that base class in your container.
    >>
    >>> I'm not very good at templates so I've certainly made a number of
    >>> silly mistakes.

    >>
    >>
    >> class OptionBase
    >> {
    >> public:
    >> OptionBase(const std::string& name)
    >> : m_name(name),
    >> m_not_set(true)
    >> {
    >> }
    >> virtual std::typeinfo get_type() const = 0;
    >> virtual ~OptionBase() {}
    >>
    >> private:
    >> std::string m_name;
    >> bool m_not_set;
    >> };
    >>
    >> template <typename T>
    >> class Option : public OptionBase
    >> {
    >> public:
    >> Option(const std::string& name)
    >> : OptionBase(name)
    >> {}
    >>
    >> T get_value() const
    >> {
    >> if(m_not_set)
    >> throw SomeException();
    >>
    >> return m_value;
    >> }
    >>
    >> void set_value(const T& value)
    >> {
    >> m_not_set = false;
    >>
    >> m_value = value;
    >> }
    >>
    >> virtual std::typeinfo get_type() const
    >> {
    >> return typeid(T);
    >> }
    >>
    >> private:
    >> T m_value;
    >> };
    >>
    >> //Don't need to derive for each type anymore - a typedef is sufficient
    >> typedef Option<Long> LongOption;
    >> typedef Option<std::string> StringOption;
    >>
    >> //...
    >> std::vector<OptionBase*> options(11);
    >> options[0] = new StringOption("Name=");
    >>
    >> //And to test for the type:
    >> if (options[0]->get_type() == typeid(std::string))
    >> {
    >> //we have a string
    >> }
    >>
    >> Another thing you might be interested in is boost::any. See
    >> http://www.boost.org/doc/html/any.html
    >>

    >
    > Very nice, Rolf! I will try out your code as soon as I've showered &
    > shaved, looks real nice! Thank you for such a detailed response.
    >
    > / Eric
    >


    Heh, I couldn't wait to try the code out..I'm having some problems...first I
    had to change std::typeinfo to std::type_info, guess that was just a simple
    typo on your part (happens all the time for me). But I'm still having
    problems with the get_type() function. The code is:

    class OptionBase
    {
    public:
    OptionBase(const std::string& name)
    :
    m_name(name),
    m_not_set(true) {}

    virtual ~OptionBase() {}

    virtual std::type_info get_type() const = 0;

    private:
    std::string m_name;
    bool m_not_set;
    };

    template<typename T>
    class Option : public OptionBase
    {
    public:
    Option(const std::string& name)
    :
    OptionBase(name) {}

    virtual std::type_info get_type() const
    {
    return typeid(T);
    }

    T get_value() const
    {
    if(m_not_set)
    throw;
    return m_value;
    }

    void set_value(const T& value)
    {
    m_value = value;
    m_not_set = false;
    }

    private:
    T m_value;
    };

    typedef Option<std::string> StringOption;

    int main()
    {
    std::vector<OptionBase*> options(11);

    options[0] = new StringOption("duh");

    return 0;
    }

    and the error is:
    /usr/include/c++/3.3.3/typeinfo: In member function `std::type_info
    Option<T>::get_type() const [with T = std::string]':
    gccmain.cpp:8: instantiated from here
    /usr/include/c++/3.3.3/typeinfo:75: error: `std::type_info::type_info(const
    std::type_info&)' is private
    option.hpp:38: error: within this context
    make: *** [gccmain] Error 1

    What am I doing wrong? I must say that I have never used type_info before.

    / Eric
    Eric Lilja, Feb 26, 2005
    #4
  5. Eric Lilja

    Eric Lilja Guest

    "Eric Lilja" <> wrote in message
    news:cvpn3q$2d4$...
    >
    > "Eric Lilja" <> wrote in message
    > news:cvplt7$240$...
    >>
    >> "Rolf Magnus" <> wrote in message
    >> news:cvpjvl$jrl$00$-online.com...
    >>> Eric Lilja wrote:
    >>>
    >>>> Hello, in my program I am reading a text file that has format:
    >>>> option=value
    >>>> There are several types of options and they expect values of different
    >>>> types (mostly strings or integers). I made a templated base class
    >>>> Option
    >>>> and had my different options derive from Option instantiated for their
    >>>> type (i.e., class LongOption inherits publicly from Option<long>). I
    >>>> selected this approach because I wanted a uniform interface for
    >>>> obtaining
    >>>> the type and value of a given option. I came up with the following
    >>>> class
    >>>> tree for testing purposes:
    >>>> template <typename T>
    >>>> class Option
    >>>> {
    >>>> public:
    >>>> enum OptionType
    >>>> {
    >>>> LONG,
    >>>> STRING
    >>>> };
    >>>
    >>> This enum must be changed whenever you add another derived type. I'd use
    >>> typeinfo instead.
    >>>
    >>>>
    >>>> Option(const std::string& name)
    >>>> :
    >>>> m_name(name),
    >>>> m_not_set(true) {}
    >>>>
    >>>> virtual ~Option() {}
    >>>>
    >>>> T get_value() const
    >>>> {
    >>>> if(m_not_set)
    >>>> throw;
    >>>
    >>> throw what?
    >>>
    >>>>
    >>>> return m_value;
    >>>> }
    >>>>
    >>>> void set_value(const T& value)
    >>>> {
    >>>> m_not_set = false;
    >>>>
    >>>> m_value = value;
    >>>> }
    >>>>
    >>>> virtual OptionType get_type() const = 0;
    >>>>
    >>>> private:
    >>>> std::string m_name;
    >>>> bool m_not_set;
    >>>> T m_value;
    >>>> };
    >>>>
    >>>> class LongOption : public Option<long>
    >>>> {
    >>>> public:
    >>>> LongOption(const std::string& name)
    >>>> :
    >>>> Option<long>(name) {}
    >>>>
    >>>> virtual OptionType get_type() const
    >>>> {
    >>>> return STRING;
    >>>> }
    >>>> };
    >>>
    >>> I don't really think you need to derive for each type if you use
    >>> typeinfo.
    >>> I'll present an example of what I mean below.
    >>>
    >>>>
    >>>> class StringOption : public Option<std::string>
    >>>> {
    >>>> public:
    >>>> StringOption(const std::string& name)
    >>>> :
    >>>> Option<std::string>(name) {}
    >>>>
    >>>> virtual OptionType get_type() const
    >>>> {
    >>>> return LONG;
    >>>> }
    >>>> };
    >>>>
    >>>> That seems to compile, but I cannot do:
    >>>> std::vector<Option*> options(11);
    >>>
    >>> Option is a template, not a type. Therefore, you cannot create a vector
    >>> of
    >>> Option pointers.
    >>>
    >>>> options[0] = new StringOption("Name=");
    >>>> The compiler complains:
    >>>> $ make gccmain
    >>>> g++ gccmain.cpp -o gccmain
    >>>> gccmain.cpp: In function `int main()':
    >>>> gccmain.cpp:6: error: use of class template `template<class T> class
    >>>> Option' as expression
    >>>> gccmain.cpp:6: error: parse error before `>' token
    >>>> gccmain.cpp:8: error: `options' undeclared (first use this function)
    >>>> gccmain.cpp:8: error: (Each undeclared identifier is reported only once
    >>>> for
    >>>> each function it appears in.)
    >>>> make: *** [gccmain] Error 1
    >>>>
    >>>> Not being able to store my different options in the same container
    >>>> makes
    >>>> reading the file with options a lot messier...are their any ways to
    >>>> solve
    >>>> this?
    >>>
    >>> Yes. Make a non-templated base class and derive your Option template
    >>> from
    >>> it. Then store pointers to that base class in your container.
    >>>
    >>>> I'm not very good at templates so I've certainly made a number of
    >>>> silly mistakes.
    >>>
    >>>
    >>> class OptionBase
    >>> {
    >>> public:
    >>> OptionBase(const std::string& name)
    >>> : m_name(name),
    >>> m_not_set(true)
    >>> {
    >>> }
    >>> virtual std::typeinfo get_type() const = 0;
    >>> virtual ~OptionBase() {}
    >>>
    >>> private:
    >>> std::string m_name;
    >>> bool m_not_set;
    >>> };
    >>>
    >>> template <typename T>
    >>> class Option : public OptionBase
    >>> {
    >>> public:
    >>> Option(const std::string& name)
    >>> : OptionBase(name)
    >>> {}
    >>>
    >>> T get_value() const
    >>> {
    >>> if(m_not_set)
    >>> throw SomeException();
    >>>
    >>> return m_value;
    >>> }
    >>>
    >>> void set_value(const T& value)
    >>> {
    >>> m_not_set = false;
    >>>
    >>> m_value = value;
    >>> }
    >>>
    >>> virtual std::typeinfo get_type() const
    >>> {
    >>> return typeid(T);
    >>> }
    >>>
    >>> private:
    >>> T m_value;
    >>> };
    >>>
    >>> //Don't need to derive for each type anymore - a typedef is sufficient
    >>> typedef Option<Long> LongOption;
    >>> typedef Option<std::string> StringOption;
    >>>
    >>> //...
    >>> std::vector<OptionBase*> options(11);
    >>> options[0] = new StringOption("Name=");
    >>>
    >>> //And to test for the type:
    >>> if (options[0]->get_type() == typeid(std::string))
    >>> {
    >>> //we have a string
    >>> }
    >>>
    >>> Another thing you might be interested in is boost::any. See
    >>> http://www.boost.org/doc/html/any.html
    >>>

    >>
    >> Very nice, Rolf! I will try out your code as soon as I've showered &
    >> shaved, looks real nice! Thank you for such a detailed response.
    >>
    >> / Eric
    >>

    >
    > Heh, I couldn't wait to try the code out..I'm having some problems...first
    > I had to change std::typeinfo to std::type_info, guess that was just a
    > simple typo on your part (happens all the time for me). But I'm still
    > having problems with the get_type() function. The code is:
    >
    > class OptionBase
    > {
    > public:
    > OptionBase(const std::string& name)
    > :
    > m_name(name),
    > m_not_set(true) {}
    >
    > virtual ~OptionBase() {}
    >
    > virtual std::type_info get_type() const = 0;
    >
    > private:
    > std::string m_name;
    > bool m_not_set;
    > };
    >
    > template<typename T>
    > class Option : public OptionBase
    > {
    > public:
    > Option(const std::string& name)
    > :
    > OptionBase(name) {}
    >
    > virtual std::type_info get_type() const
    > {
    > return typeid(T);
    > }
    >
    > T get_value() const
    > {
    > if(m_not_set)
    > throw;
    > return m_value;
    > }
    >
    > void set_value(const T& value)
    > {
    > m_value = value;
    > m_not_set = false;
    > }
    >
    > private:
    > T m_value;
    > };
    >
    > typedef Option<std::string> StringOption;
    >
    > int main()
    > {
    > std::vector<OptionBase*> options(11);
    >
    > options[0] = new StringOption("duh");
    >
    > return 0;
    > }
    >
    > and the error is:
    > /usr/include/c++/3.3.3/typeinfo: In member function `std::type_info
    > Option<T>::get_type() const [with T = std::string]':
    > gccmain.cpp:8: instantiated from here
    > /usr/include/c++/3.3.3/typeinfo:75: error:
    > `std::type_info::type_info(const
    > std::type_info&)' is private
    > option.hpp:38: error: within this context
    > make: *** [gccmain] Error 1
    >
    > What am I doing wrong? I must say that I have never used type_info before.
    >
    > / Eric
    >


    Note: It compiles if I make get_type() a non-virtual member function of the
    class Option (i.e., it doesn't appear in class ObjectBase at all). But that
    removes the one function that made my OptionBase class an abstract base
    class.

    / Eric
    Eric Lilja, Feb 26, 2005
    #5
  6. Eric Lilja

    Rolf Magnus Guest

    Eric Lilja wrote:

    > Heh, I couldn't wait to try the code out..I'm having some problems...first
    > I had to change std::typeinfo to std::type_info, guess that was just a
    > simple typo on your part (happens all the time for me).


    Yes, it was. I haven't used type_info for a while, so I forgot the
    underscore :)

    > and the error is:
    > /usr/include/c++/3.3.3/typeinfo: In member function `std::type_info
    > Option<T>::get_type() const [with T = std::string]':
    > gccmain.cpp:8: instantiated from here
    > /usr/include/c++/3.3.3/typeinfo:75: error:
    > `std::type_info::type_info(const
    > std::type_info&)' is private
    > option.hpp:38: error: within this context
    > make: *** [gccmain] Error 1
    >
    > What am I doing wrong? I must say that I have never used type_info before.


    Again, my error. std::type_info cannot be copied. Try returning it by
    reference instead:

    virtual const std::type_info& get_type() const
    {
    return typeid(T);
    }
    Rolf Magnus, Feb 26, 2005
    #6
  7. Eric Lilja

    Eric Lilja Guest

    "Rolf Magnus" wrote:
    > Eric Lilja wrote:
    >
    >> Heh, I couldn't wait to try the code out..I'm having some
    >> problems...first
    >> I had to change std::typeinfo to std::type_info, guess that was just a
    >> simple typo on your part (happens all the time for me).

    >
    > Yes, it was. I haven't used type_info for a while, so I forgot the
    > underscore :)
    >
    >> and the error is:
    >> /usr/include/c++/3.3.3/typeinfo: In member function `std::type_info
    >> Option<T>::get_type() const [with T = std::string]':
    >> gccmain.cpp:8: instantiated from here
    >> /usr/include/c++/3.3.3/typeinfo:75: error:
    >> `std::type_info::type_info(const
    >> std::type_info&)' is private
    >> option.hpp:38: error: within this context
    >> make: *** [gccmain] Error 1
    >>
    >> What am I doing wrong? I must say that I have never used type_info
    >> before.

    >
    > Again, my error. std::type_info cannot be copied. Try returning it by
    > reference instead:
    >
    > virtual const std::type_info& get_type() const
    > {
    > return typeid(T);
    > }
    >


    Thanks Rolf, I finally made it compile and run without crashing. I had to
    make m_not_set a protected (not private) member variable of class OptionBase
    and I also removed the value variable from OptionBase. The only thing that
    makes the class a bit cumbersome to use is that I have to find the proper
    type and cast it to that before being able to call set_value() or
    get_value() but I guess there's no way around that.

    / Eric
    Eric Lilja, Feb 26, 2005
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Anonymous
    Replies:
    20
    Views:
    4,288
    Pete Becker
    Mar 30, 2005
  2. Jason Heyes
    Replies:
    8
    Views:
    718
    Andrew Koenig
    Jan 15, 2006
  3. Replies:
    8
    Views:
    1,913
    Csaba
    Feb 18, 2006
  4. Rune Allnor
    Replies:
    4
    Views:
    940
    Rune Allnor
    Dec 11, 2008
  5. ssylee
    Replies:
    1
    Views:
    1,202
    Zachary Turner
    Jan 13, 2009
Loading...

Share This Page