using namespace std;
#include <vector>
#include <string>
template <class T>
struct ValNode {
string id;
T value;
};
class ValTable {
public:
ValTable();
template <class T>
void add(string,T);
const bool find(string);
void remove(string);
private:
template<class T>
std::vector<ValNode<T>*> vals;
};
complier error:error: data member 'vals' cannot be a member template
i did try to use T* value in the struct, but i didnt work out.
I didnt use any of the functions in codes yet. was just trying to compling it into *.o file (with .cpp file also).
As the error says, variables (including data members) can't be templates; only classes and functions can be.
It looks like you want the table to be able to hold values of various different types, specified at run-time according to which types are passed to add(). For that, you need dynamic types, which aren't directly supported in C++. You might consider libraries like Boost.Any or Boost.Variant for that.
On the other hand, maybe you just want to store a single type in each table, and different types in different tables. In that case, the class itself will need to be a template:
template <typename T>
class ValTable {
public:
ValTable();
void add(string,T);
const bool find(string);
void remove(string);
private:
std::vector<ValNode<T>*> vals;
};
In C++ you can have template methods in a class, but not template data members.
For example:
template<typename T, int n>
struct FixedVector {
T x[n];
FixedVector() {
for (int i=0; i<n; i++) x[i] = 0;
}
template<typename C>
void copy(const C& container) {
if (container.size() != n) {
throw std::runtime_error("Wrong size");
}
int j = 0;
for (typename C::const_iterator i=container.begin(),
e=container.end();
i!=e;
++i)
{
x[j++] = *i;
}
}
};
With the above class you can declare FixedVector<int, 5> f and call f.copy(v) where v can be for example a vector or a list or anything that has size begin and end.
So FixedVector::copy is a template method and this means that the compiler will generate a different version of it for each different type you will pass to the function.
std::vector<double> y;
y.push_back(3.4); y.push_back(5.6); y.push_back(7.8);
std::list<unsigned char> z;
z.push_back('a'); z.push_back('b'); z.push_back('c');
FixedVector<int, 3> v;
v.copy(y); // This is ok
v.copy(z); // This is ok too
C++ doesn't allow template data members because this would imply a different class size depending on how many types you are using in a specific compilation unit and this doesn't go with the C++ compilation model of one-unit-at-a-time.
Adding methods is instead fine because it doesn't affect class size, and everything can be fixed at link time by avoiding pulling multiple copies of the same method from different compilation units.
You will have to declare ValTable as template
template <class T>
class ValTable{
public:
ValTable();
//template <class T>
void add(string,T);
const bool find(string);
void remove(string);
private:
//template<class T>
std::vector<ValNode<T>*> vals;
};
You won't be able to do that ValTable needs to be a template
You can have this :
template <class T> //Make the class as template
class ValTable {
public:
ValTable();
template <class X>
void add(string,X);
const bool find(string);
void remove(string);
private:
//template<class T>
std::vector<ValNode<T>*> vals;
};
You cannot have template member values: each translation unit could access different instantiations resulting in different ibject layouts. You'd need to factor out the type in some way.
The standard library does something along the lines of what you want for std::locale: each std::locale stores a collection of differently typed objects. It is soecial purpose and can't be used for your purpose directly.
The basic idea is to automatically map each type used to an int which is then used to map the type to an instance. The vals member would then be a function template looking up the correct instance. A rough outline could look like this:
int type_index_alloc() {
static std::atomic<int> current(0);
return ++current;
}
template <typename T>
int type_map() {
static int rc = type_index_alloc();
}
class container {
struct base { virtual ~base() {} };
template <typename T>
struct value: base { T v; };
std::map<int, std::shared_ptr<base>> vals_;
public:
T& vals() {
std::shared_ptr<base>& rc(vals_[type_map<T>()]);
if (!rc) {
rc = std::make_shared<value<T>>()); }
return static_cast<value<T>&>(*rc).v;
}
};
This a just trying to show how things are being set up: I currently don't have access to a compiler. Also, the code example just provides access to an object of type T but it could easily be changed to use a std::vector<T> instead.
Related
can C++ template detect members of specific type? As code below,
template <typename T>
class Element {
};
template <typename T>
class Container {
public:
Container() {
// check if T has member which type is "Element<whatever>"
// how many Element<whatever>s?
// offset?
}
};
I have a template class named Container, and I want to check:
If the passed in type T has member which type is Element<whatever>?
If so, can I get how many members which type is Element<whatever>?
If so, can I get the offset to the beginning of the class?
Explain more about requirement 3:
What I want is to access these fields(if exist) when I get a piece of data which is cast by reinterpret_cast<T>
This is doable in C++20 if the T of Container<T> is an aggregate ; I use the boost::pfr library as it simplifies this idiom but it is easily reimplementable by hand (boost::pfr's source is very simple to read)
#include <boost/pfr.hpp>
template<typename T, typename Target>
auto count_members_of_type()
{
unsigned int count = 0;
boost::pfr::for_each_field<T>(T{}, [&] <typename U> (U&&) {
count += std::is_same_v<std::remove_reference_t<U>, Target>;
});
return count;
}
given
struct Foo {
Element<int> a, b;
Element<float> c;
std::string d;
};
then
count_members_of_type<Foo, Element<int>>() == 2
Running example on gcc.godbolt.org: https://gcc.godbolt.org/z/srhn8GfWb
I have a (generated) set of classes that look roughly like this when simplified:
class A {
public:
static const int id = 0;
typedef int value_type;
void* data; // actually pointer to int
};
class B {
public:
static const int id = 1;
typedef float value_type;
void* data; // actually pointer to float
};
There are altogether tens of these, with much fewer types. I need to create classes that calculate some derived values for all of these. Now the obvious solution would be using a template like this:
template<class T>
class Derived {
public:
typename T::value_type value;
void update(const void* data) {
value = *static_cast<typename T::value_type*>(data);
// do some calculations
}
};
But this is going to instantiate a separate class for every single parameter class A, B, and so on; most of which will be identical. The other solution would be an obvious template class like this:
template<typename T>
class Derived2 {
public:
T value;
void update(const void* data) {
value = *static_cast<T*>(data);
}
};
This would be updating the code using this class manually if the schema that classes A, B, etc., are generated from changes. Is there a way to use the value_type typedefs to generate instantiations of Derived2<int>, Derived2<float> etc., or at least match the types of manually parametrized instantiations to types A, B, etc.?
This is an embedded system, so the target is reducing the amount of identical code, even if it leads to more convoluted C++ code. Replacing the void*s with actual types would lead to code explosion in other parts of the program, so it is not done.
As posted in the comments this will do what you need:
template<class T> struct Derived : Derived2<typename T::value_type> { };
unfortunately my actual template is too full of stuff that is unrelated to my question, so i tried to put everything in a short example. Lets say, I have written the following template:
#include <vector>
template <typename T> class MyTemplate{
public:
typedef void(*MyFunc)(T);
void addFunc(MyFunc f){myFuncs.push_back(f);}
void callFuncs(T value){
for (std::size_t i=0;i<myFuncs.size();i++){myFuncs[i](value);}
}
private:
std::vector<MyFunc> myFuncs;
};
I learned already, that I can specialize this template to behave different when the passed type is a vector, so I wrote this:
template <typename T> class MyTemplate<std::vector<T> > {
public:
typedef void(*MySingleElementFunc)(T);
void addSingleElementFunc(MySingleElementFunc f){
this->mySingleElementFuncs.push_back(f);
}
void callFuncs(std::vector<T> value){
//for (std::size_t i=0;i<myFuncs.size();i++){
// myFuncs[i](value);
//}
for (std::size_t i=0;i<mySingleElementFuncs.size();i++){
for (int size_t i=0;i<value.size();i++){
mySingleElemetnFuncs[i](value[i]);
}
}
}
private:
std::vector<MySingleElementFunc> mySingleElementFuncs;
};
Now my question is, what is the most elegant way (if possible without inheritance) not only to specialize the template for the case of vector< T > but at the same time still being able to use the first templates methods where vector< T > is the template parameter. What I would like to do later is the following
void Func1(int i){}
void Func2(std::vector<int> i){}
MyTemplate<std::vector<int> > myTemplate;
myTemplate.addFunc(Func1);
myTemplate.addFunc(Func2);
Is it possible to achieve this without simply copy&paste all stuff I need from the original template, to do the same also with the specialized version? I guess I will have to use some kind of inheritance. However, I want to avoid something like this:
MyTemplate<std::vector<int> > myTemplate;
// myTemplate.addFunc(Func1); // does not work
myTemplate.addFunc(Func2);
MyVectorTemplate<std::vector<int> > myVectorTemplate;
myVectorTemplate.addFunc(Func1); // works
myVectorTemplate.addFunc(Func2);
i.e. the functionality should be determined only by the type passed to the template but not by choosing the appropriate subclass. Anyhow, I have to admit that I am a bit confused about how to inherit in this case. If it was not a template, I could write something like
class MyVectorClass : public MySingleObjectClass {}
However, the following does not make any sense:
template <typename T> MyTemplate<std::vector<T> > : public MyTemplate<std::vector<T> >
but in some sense, this is what I would like to have.
I am sorry for such a long post and I hope it is more or less clear what is my problem...
EDIT: I just found a mistake in the above code. The loop in the vector template should read
for (std::size_t i=0;i<mySingleElementFuncs.size();i++){
for (int size_t j=0;j<value.size();j++){
mySingleElemetnFuncs[i](value[j]);
}
}
i.e. each registered function should be called once for each entry in the vector. (Otherwise the template does not work if the number of registered functions is not equal to the size of the vector.)
In fact you want add functionality to the specialization, something like:
template <typename T> class MyTemplate<std::vector<T> >
{
public:
typedef void(*MySingleElementFunc)(T);
typedef void(*MyVectorFunc)(std::vector<T>);
void addSingleElementFunc(MyVectorFuncf){
this->myVcetorFuncs.push_back(f);
}
void addSingleElementFunc(MySingleElementFunc f){
this->mySingleElementFuncs.push_back(f);
}
void callFuncs(const std::vector<T>& value){
for (std::size_t i=0;i<myVectorFuncs.size();i++){
myVectorFuncs[i](value);
}
for (std::size_t i=0;i<mySingleElementFuncs.size();i++){
for (int size_t i=0;i<value.size();i++){
mySingleElemetnFuncs[i](value[i]);
}
}
}
private:
std::vector<MySingleElementFunc> mySingleElementFuncs;
std::vector<MyVectorFunc> myVectorFuncs;
};
template <typename T>
class MyTemplateBase {
// generic stuff goes here
};
template <typename T>
class MyTemplate : public MyTemplateBase<T> {
// nothing goes here
};
template <typename T>
class MyTemplate<std::vector<T>> : public MyTemplateBase <std::vector<T>> {
// specialized stuff goes here
}
If you don't want public inheritance you can use private inheritance, but then you would have to explicitly export everything inherited privately:
template <typename T>
class MyTemplate<std::vector<T>> : private MyTemplateBase <std::vector<T>> {
public:
// generic stuff re-exported
using MyTemplateBase<std::vector<T>>::Func1;
using MyTemplateBase<std::vector<T>>::Func2;
// specialized stuff goes here
}
Might still be worth it, as public inheritance is not exactly the most appropriate tool for code reuse.
I think that, since Vector is a template not a class, should be something like:
template<template <typename ...> class T /*= std::vector*/>
class SomeClass
{
T x;
};
Is there any way to get a recursive template type? I have a container for which I want to specify an underlying storage strategy. The inner template must however use the outer template's type, so it causes a loop in the type definition -- which isn't possible to specify.
About what I want:
template<typename C>
struct inner {
C * object[16];
};
template<typename T, typename Inner>
struct container {
T value;
Inner<container> holder;
};
C++11 solutions are fine (though I'm still on gcc 4.6.3).
You need to tell the compiler that Inner is a templated class:
template<typename T, template<typename> class Inner>
struct container {
T value;
Inner<container> holder;
};
I'm not sure why you're adding the Inner type template parameter, since you're defining holder to be a type based on Container and inner, both of which are available at the point you're declaring holder.
Are you planning on using any type other than struct inner as a template param to Container? If not, the following simplified code compiled and ran for me in VS2010 :
#include <vector>
#include <stdio.h>
template <typename C>
struct inner{
C * objects[16];
bool hasobj;
inner():hasobj(false){}
};
template <typename T>
class Container {
inner<Container> holder;
T value;
public:
Container(const T& valueP){
value = valueP;
}
void AddChild(Container* rhs){
holder.objects[0] = rhs; //Always using first location, just for example
holder.hasobj = true;
}
void PrintStuff()const{
if(holder.hasobj){
holder.objects[0]->PrintStuff();
}
printf("VAL IS %d\n", value);
}
};
int main(){
Container<int> c(10);
Container<int> c1(20);
c1.AddChild(&c);
c1.PrintStuff();
}
Basically, this is assuming that the container is always defining holder in terms of inner, which helps get rid of the extra template parameter, when defining Container. Hope this helps :)
arun
Ie. I want to code a class ADT that can be used like this:
myADT <type> objectA;
in the same way that someone would use a vector like:
vector <type> aVector;
I'm guessing maybe it has something to do with templates and overloading the <> operator, but how do I get it to take a data type as an argument?
Let's say you have a class that implements your ADT using a hard-coded typedef T:
class ADT
{
public:
typedef int T;
ADT();
T& operator[](size_t index);
const T& operator[](size_t index) const;
size_t size() const;
...
private:
T* p_;
size_t size_;
};
(You have to work out the internal storage and member functions that are appropriate for your actual ADT).
To change this so that you can specify T as done for std::vector etc.:
template <typename T> <-- specification of T moved to here
class ADT
{
public:
<-- typedef for T removed from here
ADT();
T& operator[](size_t index);
const T& operator[](size_t index) const;
size_t size() const;
...
private:
T* p_;
size_t size_;
};
Usage is then:
ADT<int> an_adt_int;
ADT<double> an_adt_double;
If ADT is abstract data type then you should use templates
template<class T>
struct myADT
{
// implementation, for example, two variables of type T.
T A;
T B;
};
Using
myADT<int> objectA;
objectA.A = 3;
objectB.B = 4;
myADT<char> C;
C.A = 'A';
I would recommend you to read a book or articles about C++ templates. Google "C++ template".
Templates help to adapt functionality for a type with out actually repeating code for each type, which is generic programming.
template < class T >
class foo
{
T number ;
public:
foo( T a )
{
number = a; // This can be achieved through initializer lists too.
}
};
In the above snippet, keyword template says that the following is a template. And the type is class, i.e., enclosed in <>. So, foo is a class template whose template parameter is T.
foo<int> obj(10);
The template parameter is of type int. So, the corresponding code is generated by the compiler on template intantiation. i.e.,
class foo
{
int number ;
public:
foo( int a )
{
number = a; // This can be achieved through initializer lists too.
}
};
Had if a different template parameter other than int is supplied, corresponding code would be generated by the compiler on template instantiation. For more info, MSDN Templates Tutorial. Hope it helps.
I hope it's what you are looking for
template <typename NodeType> class List;
template <typename NodeType>
class Node_List
{
...
private:
NodeType date;
Node_List< NodeType > *next_Ptr;
}
class List
{
...
private:
Node_List< NodeType > *first_Ptr;
Node_List< NodeType > *last_Ptr;
}
Using:
List < int > int_list;
List < char > char_list;
#Matt Munson,
there is an answer to the question for Tony... from cplusplus:
The format for declaring function templates with type parameters is:
template <class identifier> function_declaration;
template <typename identifier> function_declaration;
The only difference between both prototypes is the use of either the keyword class or the keyword typename. Its use is indistinct, since both expressions have exactly the same meaning and behave exactly the same way.