C++ Template, Functions define in a class? - c++

Class.h
template<class T>
struct AStruct
{
//stuff
};
class aClass
{
template<class T>
void setStruct(const AStruct<T>& s)
{
theStruct = s;
}
private:
template<class T>
AStruct<T> theStruct; //this is not liked. "multiple template parameter lists are not allowed" are one of the errors I get...
};
Quite the mess but still, I'd like to know what can be done about it... I've tried playing around a bit but with no luck... Also, only standard library please!

template<class T>
struct AStruct{
};
template<class T> //<-- the template must be here
class aClass {
public:
void setStruct(const AStruct<T>& s){
theStruct = s;
}
private:
AStruct<T> theStruct; //<-- To construct this variable
};

If you are holding a member that is a class template, then you either need a class template, or you need to provide a type for the template parameter. It seems like you need the former:
template<class T>
class aClass
{
void setStruct(const AStruct<T>& s){
theStruct = s;
}
private:
AStruct<T> theStruct; // data member is class template
};

Remove the template<class T>
template<class T>
struct AStruct{
//stuff
};
template<class T>
class aClass{
void setStruct(const AStruct<T>& s){
theStruct = s;
}
private:
AStruct<T> theStruct;
};
You already defined AStruct to be a template

Related

Differentiate between shared_ptr and normal type on compile time

I try to create a templated class, which saves the template argument as a member variable (msg_).
Now the input of the class should allow normal types like int and shared_ptr<int>.
template <typename T>
class Foo {
public:
Foo<T>() {};
private:
T msg_;
};
My problem is if the class gets initialized with shared_ptr<int>, the shared_ptr has to get initialized:
this->msg_ = std::make_shared<T*>();
I tried to solve it like this:
Foo<T>() {
if (std::is_pointer<T>::value) {
this->msg_ = std::make_shared<T*>();
}
};
, but the problem is that is has to be solved on compile time. Otherwise I can not compile.
Do you know any patterns, which solve this issue?
Thank you! and
Best regards
Fabian
You might have specialization
template <typename T>
class Foo {
public:
Foo() {}
private:
T msg_;
};
template <typename T>
class Foo<std::shared_ptr<T>>
{
public:
Foo() : msg_(std::make_shared<T>()) {}
private:
std::shared_ptr<T> msg_;
};
or create function to initialize (with overload)
template <typename> struct tag{};
template <typename T>
T foo_default_init(tag<T>) { return {}; }
template <typename T>
std::shared_ptr<T> foo_default_init(tag<std::shared_ptr<T>>)
{
return std::make_shared<T>();
}
template <typename T>
class Foo {
public:
Foo() : msg_(foo_default_init(tag<T>{})){}
private:
T msg_;
};

What template<typename> template <typename> does?

Recently I stumbled upon such piece of code:
template <typename Ta> template <typename Tb>
void SomeClass<Ta>::Function() {}
There is template function, but it has strange syntax, which I don't really understand. What does it do? Is it anwhere near template<template<typename Ta>>?
I have never met such syntax, and I am confused.
Sometimes all it needs is a complete example:
template <typename Ta>
struct SomeClass {
template <typename Tb>
void Function();
};
template <typename Ta> template <typename Tb>
void SomeClass<Ta>::Function() {}
int main() {
SomeClass<int> sc;
sc.Function<double>();
}
It is a definition of a method template of a class template.
Sometimes You need compatibility with compatible objects while writing templates. For example int and double are compatible with each other. But if you have a template class objects lets say Something<int> and Something<double> and you try to assign them it will not work. You do this especially while writing copy or move assignment operators or constructors. Let suppose we have an a class template Something.
template <typename T>
class Something {
public:
Something();
Something(const Something& obj) : data(obj.data)
{
};
private:
T data;
};
int main(){
Something<int> number;
Something<double> double_number;
Something<double> newObj(number);
}
if you try to do this, it will not compile.
To make it compile you make template of your copy constructor as in this case. To make it compile you have to something like this.
template <typename T>
class Something {
public:
Something();
template<typename E>
Something(const Something<E>& obj);
T get_data() const{
return data;
}
private:
T data;
};
template<typename T>
template <typename E>
Something<T>::Something(const Something<E>& src): data(src.get_data()){
}
int main(){
Something<int> number;
Something<double> double_number;
Something<double> newObj(number);
}
Note that we are calling the public method to assign data to this object because Something<int> and Something<double> both are of different types.

Template Class that takes a Template Class that Takes a Concrete Class

While I've seen a few posts regarding taking in template classes as a parameter into a template class I can't seem to find something that works with my code, or simply I do not understand the explanation well enough.
Ultimately, I'm looking for a template class that takes another template class which takes a standard class.
*Note: For brevity, I've only included what I believe to be sufficient information.
I've made an attempt based on the information I could find and it is shown here:
Concrete Class
class ConcreteClass {
private:
std::string words;
public:
ConcreteClass(std::string newWords);
};
#endif
Template Class template
template <class ConcreteClass>
class TemplateClass{
private:
ConcreteClass stuff;
public:
TemplateClass(ConcreteClass fillStuff);
};
#endif
template <class ConcreteClass>
TemplateClass<ConcreteClass>::TemplateClass(ConcreteClass fillStuff) {
stuff = fillStuff;
}
Base Class template
template<template<class> ConcreteClass, class TemplateClass>
class BaseClass {
private:
TemplateClass<ConcreteClass>* objPntr;
}
template<template<class> ConcreteClass, class TemplateClass>
BaseClass<TemplateClass<ConcreteClass>::BaseClass(TemplateClass<ConcreteClass>* newObj) {
objPntr = newObj;
}
template<template<class> ConcreteClass, class TemplateClass>
BaseClass<TemplateClass<ConcreteClass>::~BaseClass() {
if(objPntr) {
delete objPntr;
}
}
Main
int main() {
ConcreteClass cClass("some values");
TemplateClass tClass(cClass);
BaseClass(tClass);
return 0;
}
Firstly, you need a class or typename keyword before the template parameter name in the case of template-templates. Secondly, you should put the template<class> before TemplateClass, not ConcreteClass. TemplateClass is your templated type, so it needs that specifier:
#include <string>
// I had to make up your types because there is no definition for them
struct ConcreteClass {
std::string value;
};
template <typename T>
struct TemplateClass {
T t;
};
template<class ConcreteClass, template<class> class TemplateClass>
class BaseClass {
private:
TemplateClass<ConcreteClass>* objPntr;
// constructor needs to be declared before being defined
public:
BaseClass(TemplateClass<ConcreteClass> *objPntr);
};
template<class ConcreteClass, template<class> class TemplateClass>
BaseClass<ConcreteClass, TemplateClass>::BaseClass(TemplateClass<ConcreteClass>* newObj) {
objPntr = newObj;
}
int main() {
ConcreteClass cClass{"some values"};
TemplateClass<ConcreteClass> tClass{cClass};
BaseClass<ConcreteClass, TemplateClass> bClass(&tClass);
}

C++ specializing a member function

I need to make a class with a generic data member, that works something like istream. For all types it should be able to store data that it recieves by the << operator. I want it to work for single variables unless the class is created for char, where it should work for C strings.
template <typename T>
class foo<C>{
T* data;
public:
void operator << (T t);
};
template <typename T>
class foo<char>: public foo<T>{
public:
void operator << (char* str)
};
This is how I tried to solve it, but I get an erro saying: explicit specialization is using partial specialization syntax.
Is this what you intended?
template <typename T>
class foo
{
T* data;
public:
void operator<<(T t);
};
template <>
class foo<char>
{
public:
void operator<<(char* str);
};
If you meant to inherit behavior, you'll need something like this:
template <typename T>
class foo_impl
{
T* data;
public:
void operator<<(T t);
};
template <typename T>
class foo : public foo_impl<T>
{
};
template <>
class foo<char> : public foo_impl<char>
{
public:
void operator<<(char* str);
};
(or, even simpler by eliminating unneeded occurrences of public)
template <typename T>
class foo_impl
{
T* data;
public:
void operator<<(T t);
};
template <typename T>
struct foo : foo_impl<T>
{
};
template <>
struct foo<char> : foo_impl<char>
{
void operator<<(char* str);
};
And I would suggest some const-correctness:
template <typename T>
class foo_impl
{
T* data;
public:
void operator<<(const T& t);
};
template <typename T>
struct foo : foo_impl<T>
{
};
template <>
struct foo<char> : foo_impl<char>
{
void operator<<(const char* str);
};
You cannot specify a template type within the class declaration.
template <typename T>
class foo{
T* data;
public:
void operator << (T t);
};
Try this. It may also help to read the cplusplus.com documentation on templates. http://www.cplusplus.com/doc/tutorial/templates/

Class template with template class friend, what's really going on here?

Let's say I'm creating a class for a binary tree, BT, and I have a class which describes an element of the tree, BE, something like
template<class T> class BE {
T *data;
BE *l, *r;
public:
...
template<class U> friend class BT;
};
template<class T> class BT {
BE<T> *root;
public:
...
private:
...
};
This appears to work; however I have questions about what's going on underneath.
I originally tried to declare the friend as
template<class T> friend class BT;
however it appears necessary to use U (or something other than T) here, why is this? Does it imply that any particular BT is friend to any particular BE class?
The IBM page on templates and friends has examples of different type of friend relationships for functions but not classes (and guessing a syntax hasn't converged on the solution yet). I would prefer to understand how to get the specifications correct for the type of friend relationship I wish to define.
template<class T> class BE{
template<class T> friend class BT;
};
Is not allowed because template parameters cannot shadow each other. Nested templates must have different template parameter names.
template<typename T>
struct foo {
template<typename U>
friend class bar;
};
This means that bar is a friend of foo regardless of bar's template arguments. bar<char>, bar<int>, bar<float>, and any other bar would be friends of foo<char>.
template<typename T>
struct foo {
friend class bar<T>;
};
This means that bar is a friend of foo when bar's template argument matches foo's. Only bar<char> would be a friend of foo<char>.
In your case, friend class bar<T>; should be sufficient.
In order to befriend another same-type struct:
#include <iostream>
template<typename T_>
struct Foo
{
// Without this next line source.value_ later would be inaccessible.
template<typename> friend struct Foo;
Foo(T_ value) : value_(value) {}
template <typename AltT>
void display(AltT &&source) const
{
std::cout << "My value is " << value_ << " and my friend's value is " << source.value_ << ".\n";
}
protected:
T_ value_;
};
int main()
{
Foo<int> foo1(5);
Foo<std::string> foo2("banana");
foo1.display(foo2);
return 0;
}
With the output as follows:
My value is 5 and my friend's value is banana.
In template<typename> friend struct Foo; you shouldn't write T after typename/class otherwise it will cause a template param shadowing error.
It's not necessary to name the parameters so you get fewer points of failure if refactoring:
template <typename _KeyT, typename _ValueT> class hash_map_iterator{
template <typename, typename, int> friend class hash_map;
...
The best way to make a template class a friend of a template class is the following:
#include <iostream>
using namespace std;
template<typename T>
class B;
template<typename T>
class A
{
friend class B<T>;
private:
int height;
public:
A()//constructor
A(T val) //overloaded constructor
};
template<typename T>
class B
{
private:
...
public:
B()//constructor
B(T val) //overloaded constructor
};
In my case this solution works correctly:
template <typename T>
class DerivedClass1 : public BaseClass1 {
template<class T> friend class DerivedClass2;
private:
int a;
};
template <typename T>
class DerivedClass2 : public BaseClass1 {
void method() { this->i;}
};
I hope it will be helpful.