I know the problem in the following code, but not sure about the solution.
As the templatized parameter is MOD, in the function 'func' it is expecting MOD to be of same type for both the calle class and the class pointer passed as parameter.
template <class MOD>
class Test {
public:
void func(Test<MOD>* _ptr);
Test(MOD* _m, int _val);
int ival;
private:
MOD* _mod;
};
template <class MOD>
Test<MOD>::Test(MOD* _m, int _val) {
_mod = _m;
ival = _val;
}
template <class MOD>
void Test<MOD>::func(Test<MOD>* _ptr) {
if(ival == _ptr->ival)
std::cout << "Equal values " << std::endl;
else
std::cout << "Unequal values " << std::endl;
}
class T1 {
public:
Test<T1>* _test1;
T1() : _test1(NULL) {
_test1 = new Test<T1>(this, 4);
}
~T1() {
delete _test1; _test1 = NULL;
}
};
class T2 {
public:
public:
Test<T2>* _test2;
T2() : _test2 (NULL) {
_test2 = new Test<T2>(this, 5);
}
~T2() {
delete _test2; _test2 = NULL;
}
};
int main() {
T1 t1;
T2 t2;
t1._test1->func(t2._test2);
return 0;
}
How can i solve this ?
You need this
template <class MOD>
class Test {
public:
template<class T> void func(Test<T>* _ptr);
Test(MOD* _m, int _val);
int ival;
private:
MOD* _mod;
};
template <class MOD>
template <class T>
void Test<MOD>::func(Test<T>* _ptr) {
if(ival == _ptr->ival)
std::cout << "Equal values " << std::endl;
else
std::cout << "Unequal values " << std::endl;
}
func should be a template method inside a template class.
Related
my header code:
template <typename T>
class A
{
}
template<> class A<short>;
template<> class A<float>;
in my cpp, i want to use a map to contain different type a, like following code:
class B
{
map<int, A*> a; /* how to declare a */
public:
AddA(int key, int type)
{
if (type == 1)
{
a.insert({ key, new A<short>() });
}
else
{
a.insert({ key, new A<float>() });
}
}
template<typename T>
func(int key, T v)
{
a[key].func(v);
}
};
question: how to implement it?
edit # 0410, here is my solution:
class ABase
{
virtual void func(void* t)=0;
}
template <typename T> A;
template <short> A : public ABase
{
void func(void* t) override
{
auto value = *static_cast<short*>(t);
// do processing
}
template <float> A : public ABase
{
void func(void* t) override
{
auto value = *static_cast<float*>(t);
// do processing
}
CPP: used a map of ABase* for all the template class, and use a virtual func for all template interface
main()
{
map<int, ABase*> objs;
objs.insert({0, new A<short>()});
objs.insert({1, new A<float>()});
auto value=0;
objs[0]->func(&value);
auto value1=0.f;
objs[1]->func(&value1);
}
If you really need to have multiple types in a single map, you can use a map of std::variant. But as already mentioned in the comments, this might be a design problem.
But if you need it, you can proceed with the std::map< int, std::variant<>>. Later on, if you want to access the stored element, you have to call std::visit to pick the element which is stored in std::variant.
See the following example:
template < typename T >
struct A
{
};
// spezialize if needed, here only for demonstration purpose
template <> struct A<short> { void func(short parm) { std::cout << "A<short> with " << parm << std::endl; } };
template <> struct A<float> { void func(float parm) { std::cout << "A<float> with " << parm << std::endl; } };
class B
{
std::map<int, std::variant<A<short>*, A<float>*>> a;
public:
void AddA(int key, int type)
{
if (type == 1)
{
a.insert({ key, new A<short>() });
}
else
{
a.insert({ key, new A<float>() });
}
}
template<typename T>
void func(int key, T v)
{
std::visit( [&v]( auto ptr ) { ptr->func(v); }, a[key] );
}
};
int main()
{
B b;
b.AddA( 1, 1 );
b.AddA( 2, 2 );
b.func( 1, 99 );
b.func( 2, 100 );
}
You can't achieve the problem with templates. Template declaration is only a blueprint for a type candidate.
"A<short>" is the type not "A" itself.
You can achieve your problem through inheritance.
Edit: Code is updated according to #MSalters' comment. Thanks.
#include <iostream>
#include <map>
class A
{
public:
virtual void func(void* x) = 0;
};
class A_Short : public A
{
public:
void func(void* x)
{
short* value = static_cast<short*>(x);
std::cout << "short value: " << *value << std::endl;
}
};
class A_Float : public A
{
public:
void func(void* x)
{
float* value = static_cast<float*>(x);
std::cout << "float value: " << *value << std::endl;
}
};
template<typename T>
class A_Derived : public A
{
public:
void func(void* x)
{
T* value = static_cast<T*>(x);
std::cout << "[Derived] value: " << *value << std::endl;
}
};
class B
{
std::map<int, A*> a; /* how to declare a */
public:
void AddA(int key, int type)
{
if (type == 1)
{
a.insert({ key, new A_Short() });
}
else if(type == 2)
{
a.insert({key, new A_Derived<short>()});
}
else if(type == 3)
{
a.insert({key, new A_Derived<float>()});
}
else
{
a.insert({ key, new A_Float() });
}
}
// Assumes that user knows to use which T for any "key"
template<typename T>
void func(int key, T v)
{
a[key]->func(v);
}
};
int main()
{
B b;
b.AddA(1, 1);
b.AddA(2, 8);
b.AddA(3, 2);
b.AddA(4, 3);
short s = 1;
float f = 7.1;
short s2 = 2;
float f2 = 7.2;
b.func(1, &s);
b.func(2, &f);
b.func(3, &s2);
b.func(4, &f2);
}
I read this article about C++ factory class with a self registering capability of the concrete classes. Really like it, expecially the demangled name solution used as a key for the registered classes.
There is one main issue I would like to solve: how can we modify the factory to be able to support concrete classes with different constructor parameters?
// Dog and Cat both derive from Animal, but have different constructor parameters
class Dog : public Animal::Registrar<Dog> {
public:
Dog(int param1, std::string param2) : m_x(param1) {}
void makeNoise() { std::cerr << "Dog: " << m_x << "\n"; }
private:
int m_x;
};
class Cat : public Animal::Registrar<Cat> {
public:
Cat(bool param1) : m_flag(param1) {}
void makeNoise() { std::cerr << "Cat: " << m_x << "\n"; }
private:
bool m_flag;
};
I was thinking that maybe the parameter pack of template <class Base, class... Args> class Factory should be moved to the template <class T> struct Registrar, but I can't found a proper solution.
Full original code below
#include <iostream>
#include <memory>
#include <string>
#include <unordered_map>
#include <cstdlib>
#include <cxxabi.h>
std::string demangle(const char *name) {
int status = -4; // some arbitrary value to eliminate the compiler warning
std::unique_ptr<char, void (*)(void *)> res{
abi::__cxa_demangle(name, NULL, NULL, &status), std::free};
return (status == 0) ? res.get() : name;
}
template <class Base, class... Args> class Factory {
public:
template <class ... T>
static std::unique_ptr<Base> make(const std::string &s, T&&... args) {
return data().at(s)(std::forward<T>(args)...);
}
template <class T> struct Registrar : Base {
friend T;
static bool registerT() {
const auto name = demangle(typeid(T).name());
Factory::data()[name] = [](Args... args) -> std::unique_ptr<Base> {
return std::make_unique<T>(std::forward<Args>(args)...);
};
return true;
}
static bool registered;
private:
Registrar() : Base(Key{}) { (void)registered; }
};
friend Base;
private:
class Key {
Key(){};
template <class T> friend struct Registrar;
};
using FuncType = std::unique_ptr<Base> (*)(Args...);
Factory() = default;
static auto &data() {
static std::unordered_map<std::string, FuncType> s;
return s;
}
};
template <class Base, class... Args>
template <class T>
bool Factory<Base, Args...>::Registrar<T>::registered =
Factory<Base, Args...>::Registrar<T>::registerT();
struct Animal : Factory<Animal, int> {
Animal(Key) {}
virtual void makeNoise() = 0;
};
class Dog : public Animal::Registrar<Dog> {
public:
Dog(int x) : m_x(x) {}
void makeNoise() { std::cerr << "Dog: " << m_x << "\n"; }
private:
int m_x;
};
class Cat : public Animal::Registrar<Cat> {
public:
Cat(int x) : m_x(x) {}
void makeNoise() { std::cerr << "Cat: " << m_x << "\n"; }
private:
int m_x;
};
// Won't compile because of the private CRTP constructor
// class Spider : public Animal::Registrar<Cat> {
// public:
// Spider(int x) : m_x(x) {}
// void makeNoise() { std::cerr << "Spider: " << m_x << "\n"; }
// private:
// int m_x;
// };
// Won't compile because of the pass key idiom
// class Zob : public Animal {
// public:
// Zob(int x) : Animal({}), m_x(x) {}
// void makeNoise() { std::cerr << "Zob: " << m_x << "\n"; }
// std::unique_ptr<Animal> clone() const { return
// std::make_unique<Zob>(*this); }
// private:
// int m_x;
// };
// An example that shows that rvalues are handled correctly, and
// that this all works with move only types
struct Creature : Factory<Creature, std::unique_ptr<int>> {
Creature(Key) {}
virtual void makeNoise() = 0;
};
class Ghost : public Creature::Registrar<Ghost> {
public:
Ghost(std::unique_ptr<int>&& x) : m_x(*x) {}
void makeNoise() { std::cerr << "Ghost: " << m_x << "\n"; }
private:
int m_x;
};
int main() {
auto x = Animal::make("Dog", 3);
auto y = Animal::make("Cat", 2);
x->makeNoise();
y->makeNoise();
auto z = Creature::make("Ghost", std::make_unique<int>(4));
z->makeNoise();
return 0;
}
I have a template method inside a template class.
I read that a method can not be specialized without specialize the class before.
But I want to factorize some of theses methods, is it possible ?
Example :
class One {
public:
static const int number = 1;
};
class Two {
public:
static const int number = 2;
};
template<typename num> class A {
private:
num n;
public:
template<typename type>
void multiplyBy(); // by 1 if <int> or 1,5 if <float>
}; // A
template<> template<> void A<One>::multiplyBy<int>() {
std::cout << 1.0*n.number << std::endl;
}
template<> template<> void A<One>::multiplyBy<float>() {
std::cout << 1.5*n.number << std::endl;
}
template<> template<> void A<Two>::multiplyBy<int>() {
std::cout << 1.0*n.number << std::endl;
}
template<> template<> void A<Two>::multiplyBy<float>() {
std::cout << 1.5*n.number << std::endl;
}
int main() {
A<One> aOne;
A<Two> aTwo;
aOne.multiplyBy<int>(); // 1
aOne.multiplyBy<float>(); // 1.5
aTwo.multiplyBy<int>(); // 2
aTwo.multiplyBy<float>(); // 3
return 0;
}
A stackoverflow related question : C++ specialization of template function inside template class
In particular this comment : C++ specialization of template function inside template class
Have I to deduct than there is no way to factorize multiplyBy(), for one for int and an other for float ?
As english is not my natural language maybe I miss something simple, maybe a workaround with partial-specialization.
Edit : put A::n in private to match even better my problem.
You might use tag dispatching:
#include <iostream>
class One {
public:
static const int number = 1;
};
class Two {
public:
static const int number = 2;
};
template<typename num>
class A {
public:
num n;
private:
template<typename> struct Tag {};
void multiplyBy(Tag<int>) {
std::cout << 1.0*n.number << std::endl;
}
void multiplyBy(Tag<float>) {
std::cout << 1.5*n.number << std::endl;
}
public:
template<typename type>
void multiplyBy() {
multiplyBy(Tag<type>());
}
};
int main() {
A<One> aOne;
A<Two> aTwo;
aOne.multiplyBy<int>(); // 1
aOne.multiplyBy<float>(); // 1.5
aTwo.multiplyBy<int>(); // 2
aTwo.multiplyBy<float>(); // 3
return 0;
}
But I want to factorize some of theses methods, is it possible ?
You probably know that you cannot use:
template<> template<> void A<One>::multiplyBy<int>() {
std::cout << 1.0*n.number << std::endl;
}
without specializing A<One>.
You can do something along the lines of:
#include <iostream>
class One {
public:
static const int number = 1;
};
class Two {
public:
static const int number = 2;
};
template<typename num, typename type = int> struct MultiplyBy {
static void doit(num n)
{
std::cout << 1.0*n.number << std::endl;
}
};
template<typename num> struct MultiplyBy<num, float> {
static void doit(num n)
{
std::cout << 1.5*n.number << std::endl;
}
};
template<typename num> class A {
public:
num n;
template<typename type>
void multiplyBy()
{
MultiplyBy<num, type>::doit(n);
}
};
int main() {
A<One> aOne;
A<Two> aTwo;
aOne.multiplyBy<int>(); // 1
aOne.multiplyBy<float>(); // 1.5
aTwo.multiplyBy<int>(); // 2
aTwo.multiplyBy<float>(); // 3
return 0;
}
I have a such factories, which instantiate objects by passed template class name T:
template<class T>
class Factory0
{
public:
static void *Create(){ return new T(); }
};
template<class T, class Argument1>
class Factory1
{
public:
static void *Create( Argument1 &arg1 ){ return new T( arg1 ); }
};
And i need to do something like such:
map<string[ClassName], &factory] _builder;
...
template<class T>
Add(){
if( T derived from BaseClass ) _builder[T] = &factory1::Create
else if( T derived from BaseClass ) _builder[T] = &factory0::Create;
}
template<class T>
Create() {
return _builder[T]( (factory0) ? <nothing> : <some_argument> );
}
This is hard for two reasons:
Calling create with the wrong arguments can only be caught at runtime, so we need a bit of dynamic typing.
C++ really doesn't like casting function pointers. Or creating pointers to templated functions. Or generally doing anything complex with function pointers.
But it can be done:
#include<string>
#include<map>
#include<iostream>
using namespace std;
struct returnable {
// Put some interesting virtual functions here
};
struct foo : public returnable {
foo() {
cout << "defaulFoo" << endl;
}
foo(int x) {
cout << "Foo:" << x << endl;
}
};
struct bar : public returnable {
bar(char a, char b){
cout << "bar:" << a << "," << b << endl;
}
};
template<typename... ARGS>
struct newmakerbase {
virtual returnable* make(ARGS... args) = 0;
};
template<typename OUT, typename... ARGS>
struct newmaker : public newmakerbase<ARGS...> {
virtual returnable* make(ARGS... args) {
return new OUT(args...);
}
};
// Boost might provide a neater version of this
int nextId = 0;
template<typename... T>
struct typeId {
static const int id;
};
template<typename... T>
const int typeId<T...>::id = nextId++;
map<string,void*> builders;
map<string,int> argtypes;
template<typename OUT, typename... ARGS>
void registerClas(string name) {
builders[name] = static_cast<void*>(new newmaker<OUT,ARGS...>());
argtypes[name] = typeId<ARGS...>::id;
}
template<typename... ARGS>
returnable* create(string name, ARGS... args) {
int argsgiven = typeId<ARGS...>::id;
if (argsgiven != argtypes[name]) {
// TODO: maybe throw an exception or something?
return NULL;
}
newmakerbase<ARGS...>* builder = static_cast<newmakerbase<ARGS...>*>(builders[name]);
return builder->make(args...);
}
main() {
registerClas<foo>("defaultFoo");
registerClas<foo,int>("foo");
registerClas<bar,char,char>("bar");
returnable* a = create("defaultFoo");
returnable* b = create("foo", 42);
returnable* c = create("foo", 'a', 'b'); // returns NULL
returnable* d = create("foo", 42.0); // also returns NULL
returnable* e = create("bar", 'c', 'd');
cout << a << " " << b << " " << c << " " << d << " " << e << endl;
}
Why executing this code:
// DefaultAny.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <exception>
using std::cout;
template<class T>
struct NoReturnPolicy
{
static void calculate(T& result, const T& source)
{
result = source;
}
};
template<class T>
struct ReturnPolicy
{
static T& calculate(T& result, const T& source)
{
result = source;
return result;
}
};
template<class T>
struct ThrowPolicy
{
static void check(T* ptr)
{
cout << "ThrowPolicy";
struct Nullptr: public std::exception{};
if(!ptr)
{
throw Nullptr("Nullptr not allowed");
}
}
};
template<class T>
struct NoThrowPolicy
{
static T* check(T* ptr)
{
cout << "NoThrowPolicy";
if(!ptr)
{
return nullptr;
}
else
{
return ptr;
}
}
};
/*
If pointer already points at
something no assignement is being done
*/
template<class T, class ThrowingPolicy>
struct NoAssignPolicy
{
static T* check(T* dest,const T*const src)
{
cout << "NoAssignPolicy";
if (!ThrowPolicy::check(dest))
{
dest = operator new(sizeof(T));
new (dest) T(*src);
}
}
};
template<class T,class ThrowingPolicy>
struct NoCheckPolicy
{
static void check(T* p)
{
cout << "NoCheckPolicy";
}
};
template<class T,class ThrowingPolicy>
struct CheckPolicy
{
static void check(T* p)
{
cout << "CheckPolicy";
ThrowingPolicy::check(p);
}
};
template<
class T,
class ThrowingPolicy = NoThrowPolicy<T>,
class CheckingPolicy = NoCheckPolicy<T,ThrowingPolicy>,
class AssigningPolicy = NoAssignPolicy<T,ThrowingPolicy>,
class ReturningPolicy = NoReturnPolicy<T>
>
struct BreadSlicer
{
BreadSlicer()
{
cout << "Type: " << typeid(T).name() << '\n';
cout << "ThrowingPolicy: " << ThrowingPolicy::check(0) << '\n'; //
//<<<---------The second call to cout makes output on my console:
//NoThrowPolicy:"NoSpace"ThrowingPolicy:"Space"000000
}
};
//The words NoSpace and Space do not actually appear in my console ;) and they are in the opposite order.
int _tmain(int argc, _TCHAR* argv[])
{
BreadSlicer<int> a;
return 0;
}
See comments in first struct above main.
This is the result of unspecified behavior. If you have:
cout << a() << b() << c() << endl;
The order of execution of a, b, and c is not defined (yes, their results are added to the cout stream in a predictable order, but execution of the functions is not in defined order).
If your question is why "NoThrowPolicy" gets output before "ThrowingPolicy", the answer is that there's no sequence point guaranteeing an ordering for the call to ThrowingPolicy::check(0) and the call to operator<<(cout, "ThrowingPolicy: "). C++ is allowed to call those functions in either order.