This is a excerpt from my header file
template <typename E>
class Container {
public:
Container& operator=(const Container&) = delete;
Container(const Container&) = delete;
Container() = default;
virtual ~Container() { }
...
Then I've created another header file to declare a new class and to implement the methods (these are not shown now)
template <typename E>
class SepChaining : public Container<E> {
size_t nmax;
size_t n;
int *values;
public:
SepChaining<E>( size_t nmax ) : nmax(nmax), n(0), values( new int[this->nmax]) { }
virtual ~SepChaining<E>( );
Here I've created a new class SepChaining that inherits the Container class and I created a constructor to assign the nmax and values
Now my question: How do I create a new instance of this class? I am really confused with where I need to specify the actual template value, say int
EDIT:
Header.h
#include <iostream>
#include <functional>
enum Order { dontcare, ascending, descending };
template <typename E>
class Container {
public:
Container& operator=(const Container&) = delete;
Container(const Container&) = delete;
Container() = default;
virtual ~Container() { }
virtual void add(const E& e) { add(&e, 1); }
virtual void add(const E e[], size_t s) = 0;
virtual void remove(const E& e) { remove(&e, 1); }
virtual void remove(const E e[], size_t s) = 0;
virtual bool member(const E& e) const = 0;
};
SepChaining.h
#include <iostream>
#include "Container.h"
template <typename E>
class SepChaining : public Container<E> {
size_t nmax;
size_t n;
int *values;
public:
SepChaining<E> ( size_t nmax ) : nmax(nmax), n(0), values(new int[this->nmax]) { }
virtual ~SepChaining ();
using Container<E>::add;
virtual void add(const E e[], size_t s);
using Container<E>::remove;
virtual void remove(const E e[], size_t s);
virtual bool member(const E& e) const;
};
SepChaining.cpp
#include <iostream>
#include "SepChaining.h"
template <typename E>
SepChaining<E>::~SepChaining( ){
delete[] values;
}
template <typename E>
void SepChaining<E>::add(const E e[], size_t s) {
std::cout << "Add method";
}
template <typename E>
void SepChaining<E>::remove(const E e[], size_t s) {
std::cout << "Remove method";
}
template <typename E>
bool SepChaining<E>::member(const E &e) const {
for (size_t i = 0; i < n; ++i) {
if (values[i] == e) return true;
}
return false;
}
So these are my three files, the main.cpp is just initialising of the constructor as you told me. I can't see any problem with my code..
Simply change E to int:
SepChaining<int> instance;
Related
For a personal project, I want to create a generic graph.
I have created 2 classes: a class OrientedNode and a class ClassicArrow.
Here are the class file:
-Node Class File
#pragma once
#include <iostream>
#include <vector>
//BEGIN OF THE CLASS CLASSICNODE:MOTHER CLASS OF EVERY TYPE OF NODE
class ClassicNode{
protected:
unsigned int nodeId;
public:
//Constructor
ClassicNode();
ClassicNode(unsigned int NodeId);
//Getters
unsigned int getId()const;
//Operator
friend std::ostream& operator<<(std::ostream& outputStream, const ClassicNode& N){
return outputStream << N.getId()<<std::endl;
}
bool operator ==(const ClassicNode& N);
};
//BEGIN OF THE CLASS ORIENTEDNODE:
// -IT INHERITS THE CLASS NODE
// -IT REPRESENTS THE NODE IN A ORIENTED GRAPHE
template <typename ARROW> class OrientedNode: public ClassicNode{
protected:
std::vector<ARROW> listArrowsIn;
std::vector<ARROW> listArrowsOut;
public:
//Constructor
OrientedNode();
OrientedNode(unsigned int NodeId);
//Getter
std::vector<ARROW> getListArrowIn()const;
std::vector<ARROW> getListArrowOut()const;
//Manipulation
void addArrowIn(const ARROW& A);
void addArrowOut(const ARROW& A);
};
-Arc Class File:
#pragma once
#include <iostream>
template <typename NODE> class ClassicArrow
{
protected:
unsigned int origineNodeId;//Id of the node where the arrow begin
unsigned int destinationNodeId;//Id of the node where the arrow end
float distance;
NODE* targetNode;//Pointer to the node where the arrow end
public:
//Constructor
ClassicArrow();
ClassicArrow(const ClassicArrow<NODE>& A);
ClassicArrow(unsigned int OrigineNodeId,unsigned int DestinationNodeId,float Distance,NODE* TargetNode);
//Getters
unsigned int getOrigineNodeId()const;
unsigned int getDestinationNodeId()const;
float getDistance()const;
NODE* getTargetNode()const;
//Operator
void operator=(const ClassicArrow<NODE>& A);
NODE& operator*(void);
friend std::ostream& operator<<(std::ostream& outputStream, const ClassicArrow<NODE>& A){
return outputStream <<"IdBegin="<<A.getOrigineNodeId()<< "IdEnd="<<A.getDestinationNodeId()<<"distance="<<A.getDistance()<<std::endl;
}
};
The OrientedNode class and the ClassicArrow class are nested together.
I want to declare a OrientedNode variable with template class parameter ClassicArrow (the ligne to file in the main file). How can I do that?
#include <iostream>
#include <vector>
#include "ClassicArrow.h"
#include "ClassicNode.h"
int main() {
//Code for a Oriented Node variable declaration
}
I am learning to code with variadic template and wrote a simple variadic template to experiment. The compiler complains about the m_bindingObj member variable with template argument 1 is invalid. What I am missing?
#include <iostream>
#include <functional>
class ClassA
{
public:
static ClassA * construct(int varA, int varB, int varC)
{
return new ClassA(varA, varB, varC);
}
ClassA(int varA, int varB, int varC)
: m_varA(varA)
, m_varB(varB)
, m_varC(varC) {}
static std::function<ClassA *(int, int, int)> getBinding() { return std::bind(&ClassA::construct, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); }
int m_varA;
int m_varB;
int m_varC;
};
template <typename T>
class ToolFactory
{
public:
template <typename... Args>
static T * invoke(Args... args)
{
std::function<T*(Args...)> creator = getCreator<Args...>();
return creator(args...);
}
template <typename... Args> static std::function<T*(Args...)> getCreator() {
return T::getBinding();
}
template <typename... Args> static std::function<T*(Args...)> m_bindingObj;
};
template <typename T> std::function<T*(Args...)> ToolFactory<T>::m_bindingObj;
int main()
{
ToolFactory<ClassA>::invoke(1, 2, 3);
return 0;
}
With the fixed typo provided by bobah I have reworked the example which shows an example of the used of m_bindingObj.
#include <iostream>
#include <functional>
class ClassA
{
public:
static ClassA * construct(int varA, int varB, int varC)
{
return new ClassA(varA, varB, varC);
}
ClassA(int varA, int varB, int varC)
: m_varA(varA)
, m_varB(varB)
, m_varC(varC) {}
static std::function<ClassA *(int, int, int)> getBinding() { return std::bind(&ClassA::construct, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); }
int m_varA;
int m_varB;
int m_varC;
};
class ClassB
{
public:
static ClassA * construct(int varA, int varB, int varC)
{
return new ClassA(varA, varB, varC);
}
static std::function<ClassA *(int, int, int)> getBinding() { return std::bind(&ClassB::construct, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); }
};
template <class T>
class ToolFactory
{
public:
template <typename... Args>
static T * create(Args... args)
{
return m_bindingObj<Args...>(args...);
}
template<typename... Args> static void setBinding(std::function<T*(Args...)> functor) {
m_bindingObj<Args...> = functor;
}
template <typename... Args> static std::function<T*(Args...)> m_bindingObj;
};
template<class T> template<typename... Args> std::function<T*(Args...)> ToolFactory<T>::m_bindingObj = T::getBinding();
int main()
{
ToolFactory<ClassA>::setBinding(ClassB::getBinding());
ClassA * instance = ToolFactory<ClassA>::create(1, 2, 3);
return 0;
}
Few typos plus you need C++14 if you need the variable template syntax support. Would be great to see an example of what a m_bindingObj member variable is used for, as whether my variant is correct or not depends on that.
template <typename T>
class ToolFactory
{
...
template <typename... Args> static std::function<T*(Args...)> m_bindingObj;
};
template <typename T>
template <typename... Args>
std::function<T*(Args...)> ToolFactory<T>::m_bindingObj;
Example
In example above I've tried to store pointer-to-member_function of the overloaded function in the template-based class.
The problem is that overloaded function uses Base class as parameter and current class is template class from Derived class.
Handlers
#include <iostream>
#include <string>
class HandlerA
{
public:
void foo(const std::string& m)
{
std::cout << "HandlerA: " << m << '\n';
}
};
class IBaseHandlerB
{
public:
virtual void bar(const std::string& m) = 0;
};
class HandlerB : public IBaseHandlerB
{
public:
virtual void bar(const std::string& m) override
{
std::cout << "HandlerB: " << m << '\n';
}
};
Events
class Event
{
public:
virtual void write(HandlerA&) const = 0;
virtual void write(IBaseHandlerB&) const = 0;
};
class FancyEvent : public Event
{
public:
virtual void write(HandlerA& h) const override
{
h.foo("FancyEvent");
}
virtual void write(IBaseHandlerB& h) const override
{
h.bar("FancyEvent");
}
};
Wrapper and usage example
template <typename T, typename Event>
class HandlerWrapper
{
public:
HandlerWrapper(T&& handler, void(Event::*func)(T&) const)
: m_handlerImpl(std::forward<T>(handler))
, m_eventFn(func) {}
void call(const Event& event)
{
(event.*m_eventFn)(m_handlerImpl);
}
private:
T m_handlerImpl;
void(Event::*m_eventFn)(T&) const;
};
// ------- Usage -------
int main(void)
{
FancyEvent event;
// OK
HandlerWrapper<HandlerA, Event> h(HandlerA(), &Event::write);
h.call(event);
// Error: Candidate constructor not viable: no overload of
// 'writeWithHandler' matching
// 'void (LogEvent::*)(CEFEventHandler &) const' for 2nd argument
HandlerWrapper<HandlerB, Event> h2(HandlerB(), &Event::write);
h2.call(event);
return 0;
}
Question
How to specify correct template type to accept function-to-Base if class template argument is derived from that Base?
My goal is to pass just pointer-to-member_function to another class whenever that class is the same with type that function accepts or derived from it.
I have two classes that need to keep references of each other as follow:
template <typename S>
class H {
public:
H(const S& s): s_{s} {}
private:
const S& s_;
}
And then
template <typename H>
class S {
public:
S(const H& h): h_{h} {}
private:
const H& h_;
}
There is no way I can define anything like
Service<ItsHandler<Service<....>
Any better idea?
How about Abstract base classes and polymorphism?:
class baseHandler {
public:
virtual func1() = 0;
virtual ~baseHandler() = 0;
};
template <typename S>
class H : public baseHandler {
public:
H(const S& s): s_{s} {}
private:
const S& s_;
};
//template <typename H>
class S {
public:
S(const baseHandler& h): h_{h} {}
private:
const baseHandler& h_;
};
I know,I know. This question seems to be asked several time. But all the answers are not exactly what I want because they do not resolve the whole thing at compile time. Or they are not working on the actual compiler trio VS,XCode and GCC (without #ifdefs) using C++11 features. Or at least, they lost me during explanation. So I tried on my own:
I tried to implement a method which I can give any type. As long as the type can be converted into a std::string by using std::to_string that should be used. If it is an object of a self-written class, it should have a "toString" method, than the method should use that. It would be fine if this decisions are made during compile time. Here where I come so far:
#include <stdio.h>
#include <iostream>
#include <string>
class Test
{
public:
template <typename T> static auto has_toString_method(T& t) -> decltype(t.toString(), bool()) { return true; }
static int has_toString_method(...) { return 0; }
template< class T> static void toString(T value)
{
toString(value,has_toString_method(value) );
}
template< class T> static void toString(T value,bool)
{
value.toString();
}
template< class T,bool> static void toString(T value,int)
{
printf("It works with to_string");
}
};
class MyToStringTest
{
public:
void toString()
{
printf("It works toString");
}
};
int main ()
{
MyToStringTest tst;
Test::toString(5); // This fails because the compiler tries to resolve the bool arc.
Test::toString(tst);
return 0;
}
Besides that this code is actually not compiling on VS2012 ( I marked the line ), it also is not a full decision on compile time ( I think). What I am missing? What is the fasted, smallest way to get this running?
As addon question. Is it possible, if there are "std::to_string" failing and the "toString" missing to assert or call a "third way"?
UPDATE:
I got the bug, running in circles I was copy and pasting a definition on the wrong place instead of:
template< class T,bool> static void toString(T value,int)
{
I have (of course)to write:
template< class T> static void toString(T value,int)
{
Than It will not only compile, it also will work! But the other questions will remain.
This works:
#include <stdio.h>
#include <cstdint>
#include <iostream>
#include <string>
template<int i>
struct ToStringMethod {
template<typename T>
static void toString(T value) {
printf("It works with 3rd method\n");
}
};
template<>
struct ToStringMethod<1> {
template<typename T>
static void toString(T value)
{
value.toString();
}
};
template<>
struct ToStringMethod<2> {
template<typename T>
static void toString(T value)
{
printf("It works with to_string\n");
}
};
class Test
{
public:
template <typename T> static auto has_string_support(T& t) -> decltype(t.toString(), std::int8_t()) { return true; }
template <typename T> static auto has_string_support(T& t) -> decltype(std::to_string(t), std::int16_t()) { return true; }
static std::uint32_t has_string_support(...) { return true; }
template< class T> static void toString(T value)
{
ToStringMethod<sizeof(has_string_support(value))>::toString(value);
}
};
class MyToStringTest
{
public:
void toString()
{
printf("It works toString\n");
}
};
class NoneString {};
int main ()
{
MyToStringTest tst;
NoneString none;
Test::toString(5); // This fails because the compiler tries to resolve the bool arc.
Test::toString(tst);
Test::toString(none);
return 0;
}
Following may help:
#include <string>
#include <type_traits>
#define HAS_MEM_FUNC(name, Prototype, func) \
template<typename U> \
struct name { \
typedef char yes[1]; \
typedef struct { char dummy[2]; } no; \
template <typename T, T> struct type_check; \
template <typename T = U> \
static yes &chk(type_check<Prototype, &T::func> *); \
template <typename > static no &chk(...); \
static bool const value = sizeof(chk<U>(0)) == sizeof(yes); \
}
HAS_MEM_FUNC(has_to_string, std::string(T::*)() const, toString);
class Test
{
public:
template<typename T>
static typename std::enable_if<has_to_string<T>::value, std::string>::type
toString(const T& t) {
/* something when T has toString ... */
return t.toString();
}
template<typename T>
static typename std::enable_if<!has_to_string<T>::value, std::string>::type
toString(const T& t) {
/* something when T doesnt have toString ... */
return std::to_string(t);
}
};
class MyToStringTest
{
public:
std::string toString() const
{
return "It works toString";
}
};
int main(int argc, char** argv)
{
MyToStringTest tst;
Test::toString(5);
Test::toString(tst);
return 0;
}