Click here to Skip to main content
15,890,345 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Well, first excuse my bad English. I am making a class and I need to instantiate a class that contains within a data type that depends on a trait ...... best explained with the source code.

Imagine the following scenario... i have a class (trait) wich contains their implementations...

C++
template <typename T>
struct ClassATraits{
};

template <>
struct ClassATraits<Class>
{
	typedef Class Some;
	typedef Class::Some2 Result;

	static std::string funct(const Arg& conn)
	{
	    return Some.funct();
	}
}

struct ClassATraits<Class2>
{
	typedef Class2 Some;
	typedef Class2::Some2 Result;

	static std::string funct(const Arg& conn)
	{
	    return Some.funct();
	}
}


C++
template <typename T, typename ATraits = ClassATraits<T> >
class ClassA {
	typedef ATraits Trait;
	typedef typename ATraits::Some Some;

public:
	typedef typename ATraits::Some2 Result;

	DBConnection():
		conn()
	{
	}
}


now i have the class.....

C++
template <typename typeBD>
class Executor {
	typedef ClassA<typeBD>::Result Result; //<--- there is
public:

	Executor();
	virtual ~Executor();

	bool isActive();

	Result result();

	virtual void exec(std::string query) = 0;

protected:
	bool active;

	Result queryResult;
};


but there the gnu compiler g++ throw the error:
type ‘ClassA<typeBD, ClassATraits<T> >’ is not derived from type ‘Executor<typeBD>’
Posted

The line:
C++
typedef typename ATraits::Some2 Result;


Should probably be:

C++
typedef typename ATraits::Result Result;


Because you don't have a data member of:
C++
ClassATraits<class>::Some2


Your double declaration of ClassATraits<> looks a bit funky too.
 
Share this answer
 
v2
The first thing to try when a template doesn't work is to get rid of it - manually instantiate the thing with the class(es) you want to use and see what happens. A handy hint for developing templates is always start with a non-template class then parameterise the things that you want to vary one at a time.

When I started looking at your code the first thing that struck my eye (after the weird declaration of ClassATraits that Jack mentioned) was:
C++
typedef Class Some;

which was later used like:
C++
return Some.funct();

Which as far as I can tell is a syntax error - you can see that by getting rid of all the template guff:
C++
class A
{
	public:
		void f();
};

class B
{
	public:
		typedef A C;

	void g()
	{
		C.f();
	}
};

The compiler will tell you something like: "non-static member reference not called on a specific object" at the line C.f() (Or maybe not (VC++ tells me that there's a missing semicolon before the line). Anyway, doing that would have told you there's an error there so you ought to fix it before going all template meta-programmy on it.

Cheers,

Ash

PS: It may seem I have a downer on templates - I don't, I just despair whenever I see someone dive in without actually seeing if their code is going to be legal in at least one use case.

PPS: This might not be your fault if you're self taught. If you are more power to your elbow!
 
Share this answer
 
v2
Well, let me explain more this...... i am developing a class to make transactions with a database and today are many database types (SQLITE3, PSQL, MYSQL, etc...) and i want the my library was generic....... Then i declare a traits, a class with the abstract implementation of all the methods..... and "making" the implementations of the class for differents database types..... the all code is hear...

DBConnection.h
C++
#ifndef DBCONNECTION_H_
#define DBCONNECTION_H_

#include "DBConnectionTraits.h"

template <typename T, typename DBTraits = DBConnectionTraits<T> >
class DBConnection {
	typedef DBTraits ConnTraits;
	typedef typename DBTraits::Connection Connection;

public:
	typedef typename DBTraits::Result Result;

	DBConnection():
		conn()
	{
	}

	virtual ~DBConnection()
	{
	}

	std::string getDbName()
	{
		return ConnTraits::getDbName(conn);
	}

	std::string getHostName()
	{
		return ConnTraits::getHostName(conn);
	}

	std::string getPassword()
	{
		return ConnTraits::getPassword(conn);
	}

	int getPort()
	{
		return ConnTraits::getPort(conn);
	}

	std::string getUserName()
	{
		return ConnTraits::getUserName(conn);
	}

	void setDbName(std::string dbName)
	{
		ConnTraits::setDbName(conn, dbName);
	}

	void setHostName(std::string hostName)
	{
		ConnTraits::setHostName(conn, hostName);
	}

	void setPassword(std::string passwd)
	{
		ConnTraits::setPassword(conn, passwd);
	}

	void setPort(int port)
	{
		ConnTraits::setPort(conn, port);
	}

	void setUserName(std::string userName)
	{
		ConnTraits::setUserName(conn, userName);
	}

	const Result getResult()
	{
		return ConnTraits::getResult(conn);
	}

	void disconnect()
	{
		ConnTraits::disconnect(conn);
	}

	std::string getOptions()
	{
		return ConnTraits::getOptions(conn);
	}

	void setOptions(std::string options)
	{
		ConnTraits::setOptions(conn, options);
	}

	void connect()
	{
		ConnTraits::connect(conn);
	}

	Result exec(std::string query)
	{
		return ConnTraits::exec(conn, query);
	}

	Result exec()
	{
		return ConnTraits::exec(conn);
	}

	bool prepare(const std::string query)
	{
		return ConnTraits::prepare(conn, query);
	}

	void addBindValue(DBVariant value)
	{
		ConnTraits::addBindValue(conn, value);
	}

	Result getData()
	{
		return ConnTraits::getResult(conn);
	}

	void close()
	{
		ConnTraits::close(conn);
	}

private:
	Connection conn;
};


And the DBConnectionTraits

C++
#ifndef DBCONNECTIONTRAITS_H_
#define DBCONNECTIONTRAITS_H_

#include <iostream>
#include <string>
#include "DBVariant.h"

template <typename T>
struct DBConnectionTraits{
};

#ifdef LIB_PSQL
#include "SQLClasses/PSQL.h"
template <>
struct DBConnectionTraits<PSQL>
{
	typedef PSQL Connection;
	typedef PSQL::Result Result;

	static std::string getDbName(const Connection& conn)
	{
	    return conn.getDbName();
	}

	static std::string getHostName(const Connection& conn)
	{
	    return conn.getHostName();
	}

	static std::string getPassword(const Connection& conn)
	{
	    return conn.getPassword();
	}

	static int getPort(const Connection& conn)
	{
	    return conn.getPort();
	}

	static std::string getUserName(const Connection& conn)
	{
	    return conn.getUserName();
	}

	static void setDbName(Connection& conn, std::string dbName)
	{
	    conn.setDbName(dbName);
	}

	static void setHostName(Connection& conn, std::string hostName)
	{
	    conn.setHostName(hostName);
	}

	static void setPassword(Connection& conn, std::string passwd)
	{
	    conn.setPassword(passwd);
	}

	static void setPort(Connection& conn, int port)
	{
	    conn.setPort(port);
	}


	static void setUserName(Connection& conn, std::string userName)
	{
	    conn.setUserName(userName);
	}

	static const Result getResult(Connection& conn)
	{
		return conn.getResult();
	}

	static void close(Connection& conn)
	{
		conn.close();
	}

	static std::string getOptions(const Connection& conn)
	{
	    return conn.getOptions();
	}

	static void setOptions(Connection& conn, std::string options)
	{
	    conn.setOptions(options);
	}

	static void connect(Connection& conn)
	{
		conn.connect();
	}

	static Result exec(Connection& conn, const std::string query)
	{
		return conn.exec(query);
	}

	static Result exec(Connection& conn)
	{
		return conn.exec();
	}

	static Result getData(Connection & conn)
	{
		return conn.getResult();
	}

	static bool commit(Connection & conn)
	{
		return conn.commit();
	}

	static bool prepare(Connection & conn, const std::string query)
	{
		return conn.prepare(query);
	}

	static void addBindValue(Connection & conn, DBVariant value)
	{
		conn.addBindValue(value);
	}

	static std::string connectOptions(Connection & conn)
	{
		return conn.getOptions();
	}

	static std::string lastError(Connection & conn)
	{
		return conn.getLastError();
	}

	/*
	 * Make the query inactive before doing the rollback.
	 */
	static bool rollback(Connection & conn)
	{
		return conn.rollback();
	}
};
#endif

#ifdef LIB_SQLITE3
#include "SQLClasses/SQLITE3.h"
template <>
struct DBConnectionTraits<SQLITE3>
{
	typedef SQLITE3 Connection;
	typedef SQLITE3::Result Result;

	static std::string getDbName(const Connection& conn)
	{
	    return conn.getDbName();
	}

	static std::string getHostName(const Connection& conn)
	{
	    return conn.getHostName();
	}

	static std::string getPassword(const Connection& conn)
	{
	    return conn.getPasswd();
	}

	static int getPort(const Connection& conn)
	{
	    return conn.getPort();
	}

	static std::string getUserName(const Connection& conn)
	{
	    return conn.getUserName();
	}

	static void setDbName(Connection& conn, std::string dbName)
	{
	    conn.setDbName(dbName);
	}

	static void setHostName(Connection& conn, std::string hostName)
	{
	    conn.setHostName(hostName);
	}

	static void setPassword(Connection& conn, std::string passwd)
	{
	    conn.setPasswd(passwd);
	}

	static void setPort(Connection& conn, int port)
	{
	    conn.setPort(port);
	}


	static void setUserName(Connection& conn, std::string userName)
	{
	    conn.setUserName(userName);
	}

	static const Result getResult(Connection& conn)
	{
		return conn.getLastResult();
	}

	static void close(Connection& conn)
	{
		conn.close();
	}

	static std::string getOptions(const Connection& conn)
	{
	    return conn.getOptions();
	}

	static void setOptions(Connection& conn, std::string options)
	{
	    conn.setOptions(options);
	}

	static void connect(Connection& conn)
	{
		conn.connect();
	}

	static Result exec(Connection& conn, const std::string query)
	{
		return conn.exec(query);
	}

	static Result exec(Connection& conn)
	{
		return conn.exec();
	}

	static Result getData(Connection & conn)
	{
		return conn.getLastResult();
	}

	static bool commit(Connection & conn)
	{
		return conn.commit();
	}

	static bool prepare(Connection & conn, const std::string query)
	{
		return conn.prepare(query);
	}

	static void addBindValue(Connection & conn, DBVariant value)
	{
		conn.addBindValue(value);
	}

	static std::string connectOptions(Connection & conn)
	{
		return conn.getOptions();
	}

	static std::string lastError(Connection & conn)
	{
		return conn.getLastError();
	}

	/*
	 * Make the query inactive before doing the rollback.
	 */
	static bool rollback(Connection & conn)
	{
		return conn.rollback();
	}
};
#endif

#endif /* DBCONNECTION_H_ */


And i want this

C++
#include "DBConnection.h"

template <typename typebd="">
class Executor {
      typedef DBConnection<typebd>::Result Result; //<-- This is the error
public:
      Result execSomething ();
}
</typebd></typename>


For separated, the DBConnection work fine, but with the typedef, BUMM!!!
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900