How do I format my function to call a templated class? - c++

I'm sure there is a very easy answer, but I can't figure it out. I have written a templated class, but I want to pass that class by reference in a class function that isn't templated. Heres what I have. I get a bunch of errors. All I need to do is figure how to format the way to insert templated class into function, but I'm at a lost. Thank you and sorry if the code doesn't really help you out.
#include <iostream>
using namespace std;
template <typename T>
class Foo {
public:
Foo();
insert(const T& Item)
//And other function, just examples
};
class noFoo(){
void test(Foo <T>& foo);
int i;
int j;
int k
};
template <typename T>
void noFoo::test(Food <T>& foo)}
cout << "hi";
}
int main() {
Foo<char> wr;
test(wr);
return 0;
}

Make test a function template. I also corrected loads of syntax errors for you (class noFoo()?), removed unnecessary code, and ran clang-format for indentation.
#include <iostream>
template <typename T>
class Foo {};
class noFoo
{
public:
template <typename T>
void test(Foo<T> &);
};
template <typename T>
void noFoo::test(Foo<T> &)
{
std::cout << "hi\n";
}
int main()
{
Foo<char> wr;
noFoo{}.test(wr);
}
Since your question is tagged d, here the same code in D.
import std.stdio;
class Foo(T) {};
class noFoo
{
public:
void test(T)(Foo!(T))
{
writeln("hi");
}
};
void main()
{
auto wr = new Foo!char;
(new noFoo).test(wr);
}

Related

Nested template C++

I have a template class of the form:
template<typename ContainerType>
class ConfIntParamStat {
public:
typedef typename ContainerType::Type Type;
...
private:
void sample(int iteration) {...}
}
I would like to create a specific version of the function sample for the case when ContainerType is a Vector. Where Vector itself is a template class, but I do not know which type of values this Vector holds.
My intuition was to create this in the header file:
template<typename Type>
ConfIntParamStat<Vector<Type> >::sample(int iteration) {
...
}
But it does not compile, and the error from clang is:
error: nested name specifier 'ConfIntParamStat<Vector<Type> >::' for declaration does not refer into a class, class template or class template partial specialization
Is it possible using another syntax ?
If you didnt want to specialize the template and were looking for a member only specialization try the following
#include <iostream>
#include <vector>
using namespace std;
template <typename ContainerType>
class Something {
public:
void do_something(int);
template <typename Which>
struct do_something_implementation {
void operator()() {
cout << "general implementation" << endl;
}
};
template <typename Which>
struct do_something_implementation<vector<Which>> {
void operator()() {
cout << "specialized implementation for vectors" << endl;
}
};
};
template <typename ContainerType>
void Something<ContainerType>::do_something(int) {
do_something_implementation<ContainerType>{}();
}
int main() {
Something<double> something;
something.do_something(1);
return 0;
}
If your intent is to specialize a function, I would just overload the function like so
#include <iostream>
#include <vector>
using namespace std;
template <typename ContainerType>
class Something {
public:
void do_something(int);
template <typename Type>
void do_something(const vector<Type>&);
};
template <typename ContainerType>
void Something<ContainerType>::do_something(int) {
cout << "Called the general method for do_something" << endl;
}
template <typename ContainerType>
template <typename Type>
void Something<ContainerType>::do_something(const vector<Type>&) {
cout << "Called the specialised method" << endl;
}
int main() {
vector<int> vec{1, 2, 3};
Something<double> something;
something.do_something(1);
something.do_something(vec);
return 0;
}
This is mostly why full/explicit function template specializations are not required. Overloading allows for almost the same effects!
Note This is a great article related to your question! http://www.gotw.ca/publications/mill17.htm
You could make use of the overloading mechanism and tag dispatch:
#include <vector>
template <class T>
struct Tag { };
template<typename ContainerType>
class ConfIntParamStat {
public:
typedef typename ContainerType::value_type Type;
//...
// private:
void sample(int iteration) {
sample_impl(Tag<ContainerType>(), iteration);
}
template <class T>
void sample_impl(Tag<std::vector<T> >, int iteration) {
//if vector
}
template <class T>
void sample_impl(Tag<T>, int iteration) {
//if not a vector
}
};
int main() {
ConfIntParamStat<std::vector<int> > cips;
cips.sample(1);
}
As skypjack mentioned this approach has a little draw when using const. If you are not using c++11 (I suspect you dont because you use > > syntax for nested templates) you could workaround this as follows:
#include <iostream>
#include <vector>
template <class T>
struct Tag { };
template <class T>
struct Decay {
typedef T Type;
};
template <class T>
struct Decay<const T> {
typedef T Type;
};
template<typename ContainerType>
class ConfIntParamStat {
public:
typedef typename ContainerType::value_type Type;
//...
// private:
void sample(int iteration) {
sample_impl(Tag<typename Decay<ContainerType>::Type>(), iteration);
}
template <class T>
void sample_impl(Tag<std::vector<T> >, int iteration) {
std::cout << "vector specialization" << std::endl;
}
template <class T>
void sample_impl(Tag<T>, int iteration) {
std::cout << "general" << std::endl;
}
};
int main() {
ConfIntParamStat<const std::vector<int> > cips;
cips.sample(1);
}
Another way to approach this is composition.
The act of adding a sample can be thought of as a component of the implementation of the class. If we remove the implementation of adding a sample into this template class, we can then partially specialise only this discrete component.
For example:
#include <vector>
//
// default implementation of the sample component
//
template<class Outer>
struct implements_sample
{
using sample_implementation = implements_sample;
// implements one function
void sample(int iteration) {
// default actions
auto self = static_cast<Outer*>(this);
// do something with self
// e.g. self->_samples.insert(self->_samples.end(), iteration);
}
};
// refactor the container to be composed of component(s)
template<typename ContainerType>
class ConfIntParamStat
: private implements_sample<ConfIntParamStat<ContainerType>>
{
using this_class = ConfIntParamStat<ContainerType>;
public:
// I have added a public interface
void activate_sample(int i) { sample(i); }
// here we give the components rights over this class
private:
friend implements_sample<this_class>;
using this_class::sample_implementation::sample;
ContainerType _samples;
};
//
// now specialise the sample function component for std::vector
//
template<class T, class A>
struct implements_sample<ConfIntParamStat<std::vector<T, A>>>
{
using sample_implementation = implements_sample;
void sample(int iteration) {
auto self = static_cast<ConfIntParamStat<std::vector<T, A>>*>(this);
// do something with self
self->_samples.push_back(iteration);
}
};
int main()
{
ConfIntParamStat< std::vector<int> > cip;
cip.activate_sample(1);
cip.activate_sample(2);
}

Calling a templated member of a class

I've written a class that has a templated member function, mostly because it takes a std::vector as an argument, however I'm struggling to find a proper way to call it.
class foo(){
// ...
template <typename _t> int bar(const std::vector<_t> *values);
// ...
}
when calling this function later with:
// ...
foo c;
std::vector<int> v(5,100);
c.bar(&v);
// ...
I get the error:
error: no matching function for call to ‘foo::bar(std::vector<int>*)’
c.bar(&v);
Shouldn't foo::bar(std::vector<int>*) conform to the template parameters? Why won't it compile?
Working example:
#include <vector>
class foo{
public:
template <typename _t> int bar(const std::vector<_t> *values) {
return 1;
}
};
int main() {
foo c;
std::vector<int> v(5,100);
c.bar(&v);
}
If you really need it to not to be inline you can:
//from here
#include <vector>
class foo{
public:
template <typename _t> int bar(const std::vector<_t> *values);
};
template <typename _t> int foo::bar(const std::vector<_t> *values) {
return 0;
}
//to here - should be in header file to allow compiler to link it!
int main() {
foo c;
std::vector<int> v(5,100);
c.bar(&v);
}

c++ unordered map using templates

I am trying to declare an unordered map using templates in c++. However, as I expect the object to be one of the primitive datatypes I don't want to declare a custom class for only one object.
I've tried using :
template <class T> std::unordered_map<int, T> storedObj;
but I keep getting the error: ‘storedObj’ was not declared in this scope
a code snippet is below
#include<iostream>
#include<unordered_map>
#include<deque>
std::deque<int> freeIds;
template <class T> std::unordered_map<int, T> storedObj;
unsigned static int objIdCount=0;
const unsigned long int MAXID = 1000000000;
Can you please tell me what's wrong? Thanks.
You are doing partial template specialisation here (see http://en.cppreference.com/w/cpp/language/partial_specialization). Probably what you had in mind is a typedef-like construction but that doesn't work with templates.
With partial template specialisation you can (partially) re-implement or re-define a templated type.
One way to achieve your goal could be:
template <class T>
class my_unordered_map :
public std::unordered_map<int, T>
{
};
int main( void ) {
my_unordered_map<float> mf;
return 0;
}
Templates are used for compile-time polymorphism. You cannot instantiate a template-based class without specifying an actual datatype for that template.
A basic way to use templates would be:
#include <iostream>
using namespace std;
template <class T>
class MyClass {
T foo;
public:
MyClass(T bar) {
foo = bar;
}
void print() {
cout << foo;
}
};
int main() {
MyClass<int> c(5);
c.print(); // prints 5
return 0;
}
You can achieve what you're trying to do by extending (deriving) the unordered_map class, like this:
#include <iostream>
#include <unordered_map>
using namespace std;
template <class T>
class MyClass: public unordered_map<int, T> {
// optional extra code here
};
int main() {
MyClass<string> cstring;
cstring[0] = "foo";
cout << cstring[0] << "\n"; // prints "foo"
MyClass<double> cdouble;
cdouble[0] = 3.14; // prints 3.14
cout << cdouble[0];
return 0;
}

C++: Non generic method in generic class?

I am interested in defining a custom method for a generic class for only a particular data type. I am not sure whats a good way to implement it. I won't be able to access class variables if I place it outside the class so I think i can never get it to work that way. If i place it inside the class, its meant to work for any type T and not just the particular type. I have been able to get my code to work the latter way by just defining a generic version of it and sending only that type as input which i m interested in but is there a neater way to accomplish this?
Below is some code to make it clear
#include<iostream>
#include<string>
using namespace std;
template<typename T>
class abc
{
public:
void myvoid();
};
template<typename string>
void abc<string>::myvoid()
{
cout<<"This portion should execute only if an instance of class is called with a string parameter" ;
}
int main()
{
abc<int> int1;
abc<string> string1;
string1.myvoid(); //should work good
int1.myvoid(); //shouldnt execute myvoid
}
You can use static_assert to prevent compilation if the method in question is used with the wrong type:
#include <type_traits> // for std::is_same
template <typename T>
struct Foo
{
void foo() const {}
void bar() const
{
static_assert(std::is_same<T, int>::value, "T is not int");
}
};
int main()
{
Foo<double> fd;
fd.foo(); // OK
//fd.bar(); // ERROR: bar() only works with Foo<int>
Foo<int> fi;
fi.foo(); // OK
fi.bar(); // OK
}
Alternatively, you can use SFINAE to control the types for which the method in question exists.
template <typename T>
class Foo
{
public:
void foo() const {}
template<typename T2 = T,
typename = typename std::enable_if<std::is_same<T, int>::value>::type>
void bar() {}
};
See this related question.
This will give a linker error if you try to call bar() on a non-specialized type. This works on gcc 4.8 (see: http://ideone.com/KbwToR)
#include <iostream>
using namespace std;
struct Foo
{
template <class T>
void bar(T);
};
template<>
void Foo::bar<int>(int i)
{
cout << i << '\n';
}
int main()
{
Foo f;
f.bar(1);
f.bar("Fail!");
return 0;
}

Templates Calling Each Other's Functions

So, I have a fairly simple set of templates that I want to use together, but the compiler keeps telling me that B::a has incomplete type. Everything is forward declared, but it still doesn't work...
#include <iostream>
using namespace std;
template <typename T> class A;
template <typename T> class B;
template <typename T>
class A{
public:
void ATestFunction();
void CallBFunction();
protected:
B<T> b;
};
template <typename T>
class B{
public:
void BTestFunction();
void CallAFunction();
protected:
A<T> a;
};
template <typename T>
void A<T>::ATestFunction(){
cout << "A was used for a function call" << endl;
}
template <typename T>
void B<T>::BTestFunction(){
cout << "B was used for a function call" << endl;
}
template <typename T>
void A<T>::CallBFunction(){
b.BTestFunction();
}
template <typename T>
void B<T>::CallAFunction(){
a.ATestFunction();
}
int main()
{
A<int> dragons;
dragons.CallBFunction();
return 0;
}
I ask this because I had run into some difficulty programming some array type classes that depend on each other (implementing a two dimensional array that can be accessed like this: [][]), but this problem happened and threw a gear in the works. I made this testing program, but it still fails. I've tried both MinGW 4.7.2 and GNU g++ on Linux, and each gave me the same problem.
The core of the issue can be seen in this piece of code:
template <typename T>
class A{
B<T> b;
};
template <typename T>
class B{
A<T> a;
};
C++ is a language with value semantics, that means that B<T> b; represents an object of type B<T> (rather than a reference, like in Java or C# with reference types). That is, A<T> contains a B<T>. Now if you look at the definition of the B template you see that in turn it contains an A<T> sub object. This is basically impossible, as A<T> cannot possibly contain an object that contains A<T>. What would be the size of an A<T> object?
Without knowing the real problem to solve, I won't venture to recommend an approach, but you can consider using pointers (A<T> would contain a pointer to B<T>, not a full B<T> sub object; or similarly, B<T> could contain a pointer to A<T>; or both), or references. But it might also be the case that a deeper redesign could make more sense.
Even if you used pointers, that could not work. That would basically trigger an infinite loop of A´s and B´s being created
A creates B creates A creates B creates A...
this would work.
#include <iostream>
using namespace std;
template<typename T> class A;
template<typename T> class B;
template<typename T>
class A
{
public:
A()
{
b = new B<T>(this);
}
A(B<T>* pb)
{
b = pb;
}
void ATestFunction()
{
cout << "A was used for a function call" << endl;
}
void CallBFunction()
{
b->BTestFunction();
}
protected:
B<T>* b;
};
template<typename T>
class B
{
public:
B()
{
a = new A<T>(this);
}
B(A<T>* pa)
{
a = pa;
}
void BTestFunction()
{
cout << "B was used for a function call" << endl;
}
void CallAFunction()
{
a->ATestFunction();
}
protected:
A<T>* a;
};
int main()
{
A<int> dragons;
dragons.CallBFunction();
B<int> bdragons;
bdragons.CallAFunction();
return 0;
}
or maybe just using static functions
#include <iostream>
using namespace std;
template<typename T> class A;
template<typename T> class B;
template<typename T>
class A
{
public:
static void ATestFunction()
{
cout << "A was used for a function call" << endl;
}
void CallBFunction();
};
template<typename T>
class B
{
public:
static void BTestFunction()
{
cout << "B was used for a function call" << endl;
}
void CallAFunction();
};
template<typename T>
void A<T>::CallBFunction()
{
B<int>::BTestFunction();
}
template<typename T>
void B<T>::CallAFunction()
{
A<int>::ATestFunction();
}
int main()
{
A<int> dragons;
dragons.CallBFunction();
B<int> bdragons;
bdragons.CallAFunction();
return 0;
}