Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Inheriting from a template class

35 views
Skip to first unread message

Christopher Pisz

unread,
Apr 26, 2016, 7:30:56 PM4/26/16
to


I don't user templates often, so here I am sucking at it.
I am trying to make an interface that uses a generic type and inherit
from it to make a concrete class whose methods return that type.

Basically I am gonna have a bunch of XML parsers specific to what files
they parse all having one interface pointer type I can use.

Can someone help me with the syntax?

--- The object I am dealing with in "DailyData.h"
// Project Includes
#include "Configuration.h"


namespace Domain
{
namespace Focus
{

//------------------------------------------------------------------------------
class DailyData
{
public:

const Configuration & GetConfiguration() const;
void SetConfiguration(const Configuration & configuration);

protected:

Configuration m_configuration;
};

//------------------------------------------------------------------------------
}
}

--- The generic interface in "IXmlParser.hpp"
namespace XMLParsing
{
template <T> class IXmlParser
{
/// <summary>
/// Parses XML a string
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="xml"></param>
/// <returns></returns>
T FromString(string xml);

/// <summary>
/// Parses XML from a file
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="path"></param>
/// <returns></returns>
T FromFile(string path);
};
}

--- The concrete type in "FocusXMLReader.h"
// Project Includes
#include "IXmlParser.hpp"

// Domain Inludes
#include "DailyData.h"

// Standard Includes
#include <string>

namespace XMLParsing
{
// Intellisense complains here about the type in <>
class FocusXmlReader : IXmlParser<Domain::Focus::DailyData>
{
public:

T FromString(const std::string & xml);

T FromFile(const std::string & path);
};
}



--
I have chosen to troll filter/ignore all subthreads containing the
words: "Rick C. Hodgins", "Flibble", and "Islam"
So, I won't be able to see or respond to any such messages
---

Jens Thoms Toerring

unread,
Apr 27, 2016, 4:39:29 AM4/27/16
to
Christopher Pisz <nos...@notanaddress.com> wrote:
> I don't user templates often, so here I am sucking at it.
> I am trying to make an interface that uses a generic type and inherit
> from it to make a concrete class whose methods return that type.

> Basically I am gonna have a bunch of XML parsers specific to what files
> they parse all having one interface pointer type I can use.

> Can someone help me with the syntax?

> --- The object I am dealing with in "DailyData.h"
> // Project Includes
> #include "Configuration.h"


> namespace Domain
> {
> namespace Focus
> {

> class DailyData
> {
> public:

> const Configuration & GetConfiguration() const;
> void SetConfiguration(const Configuration & configuration);

> protected:

> Configuration m_configuration;
> };

> }
> }

> --- The generic interface in "IXmlParser.hpp"
> namespace XMLParsing
> {
> template <T> class IXmlParser

This should be

template<typename T> class IXmlParser

> {
> /// <summary>
> /// Parses XML a string
> /// </summary>
> /// <typeparam name="T"></typeparam>
> /// <param name="xml"></param>
> /// <returns></returns>
> T FromString(string xml);

This might better be

T FromString(const std::string & xml);

or do you really need to pass a copy of the string?

> /// <summary>
> /// Parses XML from a file
> /// </summary>
> /// <typeparam name="T"></typeparam>
> /// <param name="path"></param>
> /// <returns></returns>
> T FromFile(string path);

and this

T FromFile(const std::string & path);

> };
> }

> --- The concrete type in "FocusXMLReader.h"
> // Project Includes
> #include "IXmlParser.hpp"

> // Domain Inludes
> #include "DailyData.h"

> // Standard Includes
> #include <string>

> namespace XMLParsing
> {
> // Intellisense complains here about the type in <>
> class FocusXmlReader : IXmlParser<Domain::Focus::DailyData>

There's nothing wrong about this, at least as far as I can see.
At least not with the namespaces you have shown above. Perhaps
it's due to the missing 'typename' in the template class defi-
nition?

> {
> public:

> T FromString(const std::string & xml);

> T FromFile(const std::string & path);

Now, these two lines make no real sense. First, there's no
type T anywhere (except as a template argument in some other
file). And then, these functions are defined in your base
class as

Domain::Focus::DailyData FromString(string xml);

and

Domain::Focus::DailyData FromFile(string path);

Do you really want to overload the functions from the
IXmlParser class? Otherwise simply drop these two dec-
larations.
Regards, Jens
--
\ Jens Thoms Toerring ___ j...@toerring.de
\__________________________ http://toerring.de

Christopher Pisz

unread,
Apr 28, 2016, 12:57:26 PM4/28/16
to
Thanks. I just has to change T to typename and it works as expected.
For the methods FromString and ToString, yea I want to overload them,
because the domain object being returned depends on what kind of file we
are parsing, which in turn, is the reason for trying to make this
generic in the first place.

Jens Thoms Toerring

unread,
Apr 28, 2016, 3:40:03 PM4/28/16
to
Christopher Pisz <nos...@notanaddress.com> wrote:
> >> T FromString(const std::string & xml);
> >
> >> T FromFile(const std::string & path);
> >
> > Now, these two lines make no real sense. First, there's no
> > type T anywhere (except as a template argument in some other
> > file). And then, these functions are defined in your base
> > class as
> >
> > Domain::Focus::DailyData FromString(string xml);
> >
> > and
> >
> > Domain::Focus::DailyData FromFile(string path);
> >
> > Do you really want to overload the functions from the
> > IXmlParser class? Otherwise simply drop these two dec-
> > larations.

> Thanks. I just has to change T to typename and it works as expected.
> For the methods FromString and ToString, yea I want to overload them,
> because the domain object being returned depends on what kind of file we
> are parsing, which in turn, is the reason for trying to make this
> generic in the first place.

Mmmm, you are aware that you can't overload by return type?
The compiler only takes different arguments into account when
deciding what function to call, but not the type of what a
function returns.

So, having e.g.

int foo(std::string const & str);
double foo(std::string const & str);

won't work.

And, if you have to overload everything from your base class,
why make it a base class in the first place (instead of e.g.
a member variable)? Just curious (and probably missing the
point since I don't really know about the problem you're
trying to solve;-)

Christopher Pisz

unread,
Apr 28, 2016, 3:55:10 PM4/28/16
to
On 4/28/2016 2:39 PM, Jens Thoms Toerring wrote:
SNIP
> Mmmm, you are aware that you can't overload by return type?
> The compiler only takes different arguments into account when
> deciding what function to call, but not the type of what a
> function returns.
>
> So, having e.g.
>
> int foo(std::string const & str);
> double foo(std::string const & str);
>
> won't work.

I am. As far as I know the return type in derived is being defined by
the typename in base. Therefore, the return type is the same when the
template code is instantiated. At least that is what I am trying to
accomplish.


> And, if you have to overload everything from your base class,
> why make it a base class in the first place (instead of e.g.
> a member variable)? Just curious (and probably missing the
> point since I don't really know about the problem you're
> trying to solve;-)
> Regards, Jens
>

I will try to restate the problem:

I've got a file that is provided by Mickey Mouse on a daily basis and it
contains objects of type "Cheese" that he serialized to XML.

I've got a file that is provided by Megatron on a daily basis and it
contains objects of type "World Domination Plan" that he serialized to XML.

I want to have one interface type that I can use in my client program to
parse the "Cheese" or "World Domination Plan" in the same manner.

So, I've told a team to go and implement that actual parsing of "Cheese"
in a class derived from the common interface.

I've told another team to go and implement the actual parsing of "World
Domination Plan" in another class derived from the common interface.

Later on, I might get a file from Papa Smurf that contains "Recipe For
Mushroom Soup" that he serialized to XML. I'd like to be able to follow
the pattern then and not have to change my client code.

I can also easily swap out implementations to my interface in order to
provide proxy classes if I wish for unit testing code that is dependent
on the XML parsers.

I now have this code and it seems to work as expected, unless I am
missing something:

------------------------
// Standard Includes
#include <string>

namespace XMLParsing
{
template <typename T> class IXmlParser
{
public:
/// <summary>
/// Parses XML a string
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="xml"></param>
/// <returns></returns>
virtual T FromString(const std::string & xml) = 0;

/// <summary>
/// Parses XML from a file
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="path"></param>
/// <returns></returns>
virtual T FromFile(const std::string & path) = 0;
};
}

--------------------
// Project Includes
#include "IXmlParser.hpp"

// Domain Inludes
#include "DailyData.h"

// Standard Includes
#include <string>

namespace XMLParsing
{
class FocusXmlReader : public IXmlParser<Domain::Focus::DailyData>
{
public:

Domain::Focus::DailyData FromString(const std::string & xml);

Domain::Focus::DailyData FromFile(const std::string & path);
};
}

------------------
// Project Includes
#include "FocusXmlReader.h"

// Shared Library
#include "StringUtility.h"

// Standard Includes
#include <memory>
#include <sstream>
#include <string>
#include <stdexcept>

//------------------------------------------------------------------------------
const static std::string path = "C:\\Temp\\Focus\\07132014-4544-D.FTPQ";

//------------------------------------------------------------------------------
void ParseUsingPugiXml()
{
std::unique_ptr<XMLParsing::IXmlParser<Domain::Focus::DailyData> >
parser(new XMLParsing::FocusXmlReader());
Domain::Focus::DailyData dailyData = parser->FromFile(path);
0 new messages