Passing values to inner class via template arguments C++ - c++

Trying to pass the value to nested class via template agrument,and have some confusion:
template<typename A,typename B>
class outter{
int a;
T* p;
////...////
template<typename N=int> class inner;
inner do_something(){
return inner<a>(p)
}
}
template<typename T,typename A, typename N=int>
class outter<T,A>::inner<N>{
sz=N;
}
Task is to create an iterator for vector with range control.
For now im stuck in inner class template declaration and passing arguments. Please, i need advance if that possible. Thanks!

For the inner class, you have template <typename N>, which means that your N is a type, not a value, hence, you cannot assign it to a value.
To solve your issue, try having template <int N> class inner; and also fix the same way at the bottom template<typename T, typename A, int N>
Edit
Just noticed, that at the bottom you have the inner class definition. What you want this sz to be? is it a value or type? In case you want this to be a value, you should write
template<typename T,typename A, int N> // this last int determines also the type to be used down below v
class outter<T,A>::inner<N>{
int sz=N; // this int comes from the upper side ^
}
If you want the sz to be a type defining the sizes within the inner class, then keep the upper and bottom parts to be <..., typename N = int> and put using before sz=N;
template<typename T,typename A, typename N=int>
class outter<T,A>::inner<N>{
using sz=N;
}
If you want to have N type and value be specified through templates, please follow this example:
template </*outer template params*/>
class outer {
template <typename SIZE_TYPE, SIZE_TYPE VALUE = SIZE_TYPE()>
class inner;
};
template </*outer template params*/, typename SIZE_TYPE, SIZE_TYPE VALUE = SIZE_TYPE()>
class outer</*params*/>::inner<SIZE_TYPE, VALUE> {
using size_type = SIZE_TYPE;
size_type my_value = VALUE;
}
Edit 2
In case you want to understand what happens here, please read more about the template instantiation.

Related

How to specify constructor within three template arguments

I have to define the priority_queue class in the main.
int main(){
...
pri_queue_t<string, vector_t<string>, cmp> q3;
...
}
Therefore, I tried to make a header file like below.
template<typename T, class V, class O> //the last argument is alphabet 'O'
class pri_queue_t{
public:
pri_queue_t(); //constructor
....
}
template<typename T, class V, class O>
pri_queue_t<T, V, O>::pri_queue_t(){} //body of constructor**
The error code is
/home/mys/Desktop/stl_project/2_adp/main.cc: In function ‘int main()’:
/home/mys/Desktop/stl_project/2_adp/main.cc:147:43: error: ‘cmp’ was
not declared in this scope; did you mean ‘bcmp’?
147 | pri_queue_t<string, vector_t<string>, cmp> q3;
| ^~~
| bcmp
/home/mys/Desktop/stl_project/2_adp/main.cc:147:46: error: template
argument 3 is invalid
147 | pri_queue_t<string, vector_t<string>, cmp> q3;
I meant the cmp as option that makes pri-queue ascending. How to make the right constructor? And How to define the cmp?
Priority queue is:
template<
class T,
class Container = std::vector<T>,
class Compare = std::less<typename Container::value_type>
> class priority_queue;
Note the default for the thrid parameter. If you do not know what else to put there then the default is probably fine:
template<typename T, class V>
class pri_queue_t{
public:
pri_queue_t(); //constructor
....
}
template<typename T, class V>
pri_queue_t<T, V>::pri_queue_t(){} //body of constructor**
I am a bit confused by //the last argument is alphabet 'O', because the third parameter for priority_queue is a comparator, not an "alphabet". Anyhow, then in main:
int main(){
pri_queue_t<string, vector_t<string>> q3;
}
If vector_t is std::vector, you could also get rid of the second parameter.
Alternatively you can use the defaults from the priority_queue:
#include <queue>
template <typename T>
struct prio_queue_defaults {
using container_type = typename std::priority_queue<T>::container_type;
using value_compare = typename std::priority_queue<T>::value_compare;
};
template <typename T,
typename container = typename prio_queue_defaults<T>::container_type,
typename compare = typename prio_queue_defaults<T>::value_compare>
struct my_prio_queue {
std::priority_queue<T,container,compare> x;
};
int main() {
my_prio_queue<int> y;
my_prio_queue<int,std::vector<int>> z;
}
Note that there is no need to write a constructor for this simple example, because the compiler generated one already does the right thing.
(The trait prio_queue_defaults is not really needed here and it also does not help to write less code, I just used it to have meaningful names.)

template template function definition

I have a template class called Array
template<typename T, int dimension>
class Array<typename T, int dimension>{
//definition of the class
}
I want to write a non-member function cast such that I can cast Array into different type. For example
Array<int, 2> a;
Array<float, 2> b = cast<float>(a);
How should I write this function? I am more interested in how to declare it instead of how to implement the detailed casting. I have tried
template<template<typename T, int dimension> class Array, typename New_T, int dimension>
Array<typename New_T, int dimension> cast(Array<typename T, int dimension> a){
// detailed implementation of casting, which I do not care for this question.
}
but it cannot pass the compilation.
You don't need template template parameters at all here. Simple typename and int parameters will do:
template <typename T, int dimension>
class Array
{
// ...
};
template <typename NewT, typename T, int dimension>
Array<NewT, dimension> cast(const Array<T, dimension>& a)
{
// ...
}
Live Demo
You only need template template parameters when you want to accept different types of templates. For instance, if you wanted cast to be able to accept an Array or a std::array, you could use a template template parameter:
template<typename NewT, typename T, auto dimension, template<typename, auto> typename ArrayT>
ArrayT<NewT, dimension> cast(const ArrayT<T, dimension>& a)
{
// ...
}
Live Demo
Note in this case I also changed the type of dimension to auto since std::array uses a size_t for its dimension while your Array uses int.
How should I write this function? I am more interested in how to define it instead of how to implement the detailed casting.
I suppose something like
template <typename ToT, typename FromT, int Dim>
Array<ToT, Dim> cast (Array<FromT, Dim> const & inA)
{
// ...
}
It's useful place ToT (to-type) in first position so you can explicit it and let FromT and Dim deduced from the inA value.
--- EDIT ---
The OP asks
Any insight why I have to put it [ToT] in the first position?
You don't necessarily have to put ToT in first position. But this simplify your life.
The point is that FromT and Dim are deducible from the inA argument; ToT isn't deducible from arguments so you have to explicit it.
But if you want to explicit a template parameter, you necessarily have to explicit the preceding parameters. So if you put ToT in last position, you have to call cast() explicating all template parameters
cast<int, 2, float>(a);
If you place ToT in first position, you have to explicit only it and leave the compiler deduce FromT and Dim from the argument
cast<float>(a);

A recursive template type for a container / typename forwarding

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

Variadic Template Template

I am trying to create a base class that is a wrapper around std::array that overloads a bunch of common arithmetic operators. The end result will be sort of like std::valarray, but with static size. I'm doing this because I am creating a whole host of child classes for my library that end up replicating this functionality. For example, I need to create a MyPixel class and a MyPoint class, both of which are essentially just statically sized arrays that I can perform arithmetic on.
My solution is to create a StaticValArray base class from which MyPoint and MyPixel can derive. However to disallow users from adding a MyPoint to a MyPixel, I'm using the CRTP pattern as such:
template<class T1, class T2>
struct promote
{
typedef T1 type; // Assume there is a useful type promotion mechanism here
};
template<class T, size_t S, template<typename... A> class ChildClass>
class StaticValArray : public std::array<T,S>
{
public:
// Assume there are some conversion, etc. constructors here...
template<class U>
StaticValArray<typename promote<T,U>::type,S,ChildClass> operator+
(StaticValArray<U,S,ChildClass> const & rhs)
{
StaticValArray<typename promote<T,U>::type,S,ChildClass> ret = *this;
std::transform(this->begin(), this->end(),
rhs.begin(), ret.begin(), std::plus<typename promote<T,U>::type>());
return ret;
}
// More operators....
};
This is pretty cool, because the ChildClass can have any arbitrary class template parameters, and this thing will work. For example:
template<class T, class U>
class MyClassTwoTypes : public StaticValArray<T,3,MyClassTwoTypes>
{ };
template<class T, class U>
class MyClassTwoTypes2 : public StaticValArray<T,3,MyClassTwoTypes2>
{ };
int main()
{
MyClassTwoTypes<int, float> p;
MyClassTwoTypes<double, char> q;
auto z = p + q;
MyClassTwoTypes2<double, char> r;
// r += q; // <-- Great! This correctly won't compile
return 0;
}
My problem is this: I would like to stuff some ChildClass into the CRTP bit of StaticValArray that doesn't necessarily have just classes as its template parameters. For example, consider this N-Dimensional Point class:
template<class T, size_t S>
class MyPointND : public StaticValArray<T,S,MyPointND>
{ };
This unfortunately won't compile, because size_t is not a typename - I get the compiler error:
type/value mismatch at argument 3 in template parameter list for ‘template<class T, long unsigned int S, template<class ... A> class ChildClass> class StaticValArray’
test.C:36:54: error: expected a template of type ‘template<class ... A> class ChildClass’, got ‘template<class T, long unsigned int S> class MyPointND’
Is there any way to create a variadic template template parameter pack that can be absolutely anything (typenames, ints, size_t's, doubles, whatever?) because in the end I really don't care what the type is in there. Note that I can't just fully specify ChildClass (e.g. class MyPointND: public StaticValArray<T,S,MyPointND<T,S>>) because this would break my type promotion mechanism.
What if, in place of the size_t, you used an std::integral_constant? You would embed the numerical value of the size of your array in it, and you could use it as a type.
EDIT
In order to reduce the verbosity, you could define your own integral constant class, something like:
template <std::size_t N>
struct size_ : std::integral_constant<std::size_t,N> {};
Then you could use it like this:
MyPointND<int,size_<3>> x;
What you need to do is have a traits class, specialized for each type containing whatever you need for type promotion, and then pass in the complete type to the StaticValArray.
Moreover, with decltype, you shouldn't need anything like this- decltype will tell you what you get by adding a float and an int.
template<class U>
StaticValArray<decltype(*(T*)nullptr + *(U*)nullptr),S,ChildClass> operator+
(StaticValArray<U,S,ChildClass> const & rhs)
{
StaticValArray<decltype(*(T*)nullptr + *(U*)nullptr),S,ChildClass> ret = *this;
std::transform(this->begin(), this->end(),
rhs.begin(), ret.begin(), std::plus<decltype(*(T*)nullptr + *(U*)nullptr)>());
return ret;
}

Can you help me understand this C++ template code?

Hya,
Can anyone please tell me how this thing is working?
template <typename T,
template <typename ELEM> class CONT = std::deque >
class Stack {
private:
CONT<T> elems; // elements
public:
void push(T const&); // push element
void pop(); // pop element
T top() const; // return top element
bool empty() const { // return whether the stack is empty
return elems.empty();
}
};
What i don't understand is this :
template class V or say this "template class CONT = std::deque"
i visualize this as
template <class>
class CONT = std::deque // here CONT is templatized class declaration.
but what pesters me is , how can we assign something to class name CONT , rather than writing its definition (which i've done till this time):
template <class>
class CONT{
//def
}
one more thing :
template <class> // why its only class written in angle bracket there should be also be name
like : template<class ty>
Thanks a lot , any help is very appreciated)
What i don't understand is this : template class V
There is no such line in your question, so I can't help with that.
template< template <typename ELEM> class CONT = std::deque >
class Stack
This is a declaration of a template template parameter. You pass a template into the Stack template, and then Stack can use it internally.
The = std::deque part is a default value, in case you leave the CONT parameter unspecified. (std::deque is a predefined template.)
However, this will not work, because std::deque takes two arguments. This will work:
template< template <typename ELEM, typename ALLOC> class CONT = std::deque >
class Stack
However ELEM and ALLOC do not actually name anything; they exist merely to clarify what the parameter list of the required template is. So, you can omit them:
template< template <typename, typename> class CONT = std::deque >
class Stack
It's not an object assignment. It's just syntax in a template specifier to specify what the default type argument should be if one is not provided. It's not a definition for that type.