Cast Queue Elements C++ - c++

I want to implement a custom queue class so I have done most of the work but I have a problem I want to implement casting of the type of the queue elements. Below it my code so
I am stuck how to continue implementing the casting as it should cast the elements of the queue to another type using static_cast
template<typename T, int N>
class Queue
{
private:
std::vector<T> elems;
public:
<return type> cast(void) {}
}

You could implement it as a member template although that would be somewhat annoying in contexts where it becomes a dependent name (it look as if you have a ring buffer; to keep things simple I'm using a std::deque instead):
template <typename T, int N>
class Queue {
//
std::deque<T> elems;
public:
template <typename O>
O cast() { return static_cast<O>(this->elems.back()); }
};
template <typename Q>
void f(Q& q) {
q.template cast<int>(); // "template" needed because it is a dependent name
}
int main() {
Queue<short> q;
// ...
q.cast<int>(); // doesn't need this annoying extra "template"
}
The way to avoid the necessity of the template in a dependent context is to not use a member function. I'd just define a friend function inside the Queue definition:
template <typename O>
friend O cast(Queue& q){ return static_cast<O>(q.back()); }
// ...
cast<int>(q);
To see it live use the Compiler Explorer link.

Related

Recursive function acting on variadic class template parameters

So I have the following (cut down) classes:
template <typename A, typename... B>
struct ComponentTupleAccessor:
public ComponentArray<A>,
public ComponentTupleAccessor<B...>
{
ComponentTupleAccessor(const uint32_t capacity):
ComponentArray<A>(capacity),
ComponentTupleAccessor<B...>(capacity)
{}
};
template <typename A>
struct ComponentTupleAccessor<A>:
public ComponentArray<A>
{
ComponentTupleAccessor<A>(const uint32_t capacity):
ComponentArray<A>(capacity)
{}
};
template <typename A, typename ...B>
class ComponentTuple {
ComponentTupleAccessor<A, B...> m_Components;
uint32_t m_Capacity;
public:
ComponentTuple(const RB32u capacity):
m_Capacity{capacity},
m_Components(capacity)
{}
template <typename S, typename ...T>
void pop_back() {
m_Components.Component<S>::pop_back();
pop_back<T...>();
}
template <typename S>
void pop_back() {
m_Components.Component<S>::pop_back();
}
void pop_back() {
pop_back<A, B...>();
}
};
The ComponentArray class is basically a wrapper around a vector that holds a bunch of components of a particular type.
The ComponentBlockTupleAccessor class more or less emulates a cut down version of std::tuple where the any number of unique types of ComponentArray can be inherited into the class ComponentTuple using the variadic templates.
The pop_back function in ComponentTuple is designed to recursively pop_back an element off each of the ComponentArrays.
Outside of the ComponentTuple class I'd like to be able to simply call something like compTupleInstance.pop_back() and all ComponentArray's should have their last elements removed.
I get a compile error "call of overloaded ‘pop_back()’ is ambiguous" pop_back();
I can't seem to figure out a combination of the A, B (pack), S, and T (pack) template parameters that gives me the functionality I need. What am I missing here?
Edit: Here is a simple usage scenario:
// ComponentTuple contains an int and a float ComponentArray with capacity 8.
ComponentTuple<int, float> dut(8);
// Push a set of new components to the ComponentArrays.
// This function has a similar structure to that of pop_back.
dut.push_back({8}, {3.141f});
// Another one
dut.push_back({4}, {2.718f});
// Remove the last element from all of the ComponentArrays.
dut.pop_back();
ComponentTuple template parameters will always be unique types, and there will always be greater than one.
A copy from the question:
template <typename S, typename ...T> // T can be empty
void pop_back() {
m_Components.Component<S>::pop_back();
pop_back<T...>();
}
template <typename S>
void pop_back() {
m_Components.Component<S>::pop_back();
}
If I invoke pop_back<A>() I have S = A. But, am I calling the first method with T empty, or am I calling the second method?
The core issue: template <typename S, typename ... T> and template <typename S> look equally good for the compiler when there is only one template argument (the pack can be empty). It cannot make a decision on which overload to use.
Solution: You can use fold expression (c++17 or above).
void pop_back() {
(m_Components.ComponentArray<A>::pop_back(), ... , m_Components.ComponentArray<B>::pop_back());
}
...Also the code breaks (even with the fold expression above) if used like this:
ComponentTuple<int, int, double> (ambiguous base class).
Thanks for your help guys, the ambiguity between <typename S> and <typename S, typename... T> seems obvious now that you've pointed it out. It seems it's just not possible to do it the way I was trying to, for that reason.
I ended up using a if constexpr to test if the recursion is at the last Type, so I can terminate the recursion at that point. I like this even better since in the non templated pop_back there is no risk of giving template parameters that weren't used in declaring the class. e.g.
ComponentTuple<int, float> dut(8);
push_back<Banana, char>; // Not int, float so should cause compile error.
Using the constexpr method, I can privatise the pop_back function (see pop_back_ below), and only expose the no-params version so that the method can only be called in the correct way:
template <typename A, typename ...B>
class ComponentTuple {
ComponentTupleAccessor<A, B...> m_Components;
uint32_t m_Capacity;
template <typename S, typename... T>
void pop_back_() {
m_Components.ComponentBlock<S>::pop_back();
if constexpr (sizeof...(T) > 0) {
pop_back_<T...>();
}
}
public:
ComponentTuple(const RB32u capacity):
m_Capacity{capacity},
m_Components(capacity)
{}
void pop_back() {
pop_back_<A, B...>();
}
};
Obviously I need to make sure I'm using at least c++17 to use if constexpr.

Class with member that uses variadic template

I'm trying to understand how templates work, and I've come up with this problem. Now, I'm perfectly aware that it can be solved using polymorphism, but I'm curious to see if it can be solved by just using templates. The situation is as follows:
Suppose I have two types of queues, which are defined as follows:
#include <queue>
template <typename GenType, typename Comparator>
class Priority
{
public:
Priority()
{ }
~Priority()
{ }
void insert(GenType const& t)
{ mQueue.push(t); }
private:
std::priority_queue<GenType, std::vector<GenType>, Comparator> mQueue;
};
template<typename GenType>
class FIFO
{
public:
FIFO()
{ }
~FIFO()
{ }
void insert(GenType const& t)
{ mList.push_front(t); }
private:
std::deque<GenType> mList;
};
And now, I have a class that can use either Queue or FIFO (or any other type of queue) as shown here:
// I'm not sure that this is how it should be declared...
template <typename GenType,
template<typename, typename...> class List>
class User
{
public:
User()
{ }
~User()
{ }
void add(GenType const& t)
{ mList.insert(t); }
private:
// This line gives an error.
List mList;
};
As it stands, the marked line gives an error, which I understand since I haven't actually passed any template parameters to List. The thing is that I don't know how to solve this error.
To give some context, the use case for this was to be able to have the User class take a any type of queue and could be used like this:
User<int, FIFO> u1;
// Not sure if it is this way:
User<int, Priority, std::less<int>> u2;
// Or this way:
User<int, Priority, std::less> u2;
Any suggestions on how to solve this problem?
Don't do it that way.
Instead, let your User class template take the full type of the container it's going to use, and let the container indicate what type of values it takes:
template <typename Container>
class User
{
public:
using value_type = typename Container::value_type; // you'll have to add this
// typedef to your containers
User() = default;
~User() = default;
void add(value_type const& t)
{
mList.insert(t);
}
private:
Container mList;
};
This way, I, as the user of your class template, can provide the right thing. If I want to use your priority queue, I can pass in the comparator I want directly:
User<Priority<int, std::less<>>> u;
Or not:
User<FIFO<int>> u2;
Or maybe I wrote my own container which isn't even a class template:
User<SpecialContainer> u3;
Yours works either way. Generic is good.
There is already an accepted answer, but I'd like to show the desired syntax.
private:
// This line doesn't give an error.
List<GenType> mList;
};
Now this line compiles too:
User<int, FIFO> u1;
The last two lines can't be compiled because the template User accepts only two parameters. Just add a third parameter.

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

Partial Specialization of Operator()

One of my classes declares a templated function:
template<class A, class B>
A do_something(const std::vector<B> &data)
which I'd like to partially specialize on typename A. B is a family of types that implement a pretty minimal interface, and we use a lot of them, so I'd like my specialization to be generic on B. I suspect this is doubly vexing as typename A is used only as the return type.
From the internet, I've gleaned that I can't partially specialize a function, so I've created a class as follows:
template<class A, class B>
class do_something_implementation {
public:
do_something_implementation(const std::vector<B> &data_) {
data = data_;
}
int do_something_implementation<int, B>::operator()() {
/* Complicated algorithm goes here... */
}
double do_something_implementation<double, B>::operator()() {
/* Different complicated algorithm goes here... */
}
private:
std::vector<B> data;
}
When I try to compile that (using Visual Studio 2008), the compiler crashes (!) and I get the following error:
fatal error C1001: An internal error has occurred in the compiler.
I assume this is my problem and not the compiler's. Is there a better way to express the partial specialization I'm aiming for?
Usually, it goes like this:
template <typename A, typename B>
struct DoSomethingHelper
{
static A doIt(const std::vector<B> &data);
};
template <typename B>
struct DoSomethingHelper<double, B>
{
static double doIt(const std::vector<B> &data) { ... }
};
template <typename B>
struct DoSomethingHelper<int, B>
{
static int doIt(const std::vector<B> &data) { ... }
};
template<class A, class B>
A do_something(const std::vector<B> &data)
{ return DoSomethingHelper<A, B>::doIt(data); }
Now that you've seen the classic forward to static method, there is actually another way when the type for which to specialize is "complete".
You may not be able to partially specialize a function, but you can perfectly overload it.
template <typename A, typename B>
A do(std::vector<B> const& data) { return this->doImpl(data, (A*)0); }
template <typename A, typename B>
A doImpl(std::vector<B> const& B, A*) { // generic implementation }
template <typename B>
int doImpl(std::vector<B> const& B, int*) { // int implementation }
template <typename B>
double doImpl(std::vector<B> const& B, double*) { // double implementation }
The trick is to pass an "unused" argument to doImpl for the sole purpose of actually selecting the right implementation (thanks to overload resolution).
Here I simply chose to pass (A*)0, because this does not involve A's constructor (in case it's non trivial).
This dispatch idiom is what is used in the STL to implement some algorithm with better efficiency for some iterator categories (for example, std::distance is O(1) for random iterators).
I find it much more lightweight that using a helper class with static methods and partial specializations... but maybe that's just me :)
People typically just forward to a static implementation.
template<class A, class B> class X;
template<class A, class B> friend class X;
template<class A, class B> class X {
public:
static A do_something(class_type* not_this, const std::vector<B>& data) {
//...
}
};
// partially specialize
template<class A, class B>
A do_something(const std::vector<B> &data) {
return X<A, B>::do_something(this, data);
};
Not a solution to your problem (there are a couple already there), but some of the things that are wrong in your code:
You are missing a struct or class keyword in the template class declaration:
template <typename A, typename B> struct do_something_implementation {
// ^^^^^^
Inside the class definition, member functions must not use a qualified name, regardless of whether the class is a template or not:
class A {
void A::foo() {} // Error, should be: void foo() {}
};
Member template specializations cannot appear inside the class definition, but at the namespace level:
class B {
template <typename T> void foo( T );
};
template <> void B::foo<int>( int ) {}
template <> void B::foo<double>( double ) {}
Plus on your case, the member function is not a template, but rather a non-templated member function (the template is the containing class, not the function itself). What your code is effectively trying to do is defining other class' member functions inside the general template, kind of trying to do.
Overall there was enough errors to make parsing the code almost impossible for the compiler to identify what you were trying to do and provide a good error message, but still, it should have provided any error message pointing to the first line that you copied instead of chocking to death.

simple C++ templates suited for STL Containers

I need a template like this, which work perfectly
template <typename container> void mySuperTempalte (const container myCont)
{
//do something here
}
then i want to specialize the above template for std::string so i came up with
template <typename container> void mySuperTempalte (const container<std::string> myCont)
{
//check type of container
//do something here
}
which doesnt't work, and throws an error. I would like to make the second example work and then IF possible i would like to add some code in the template to check if a std::vector/std::deque/std::list was used, to do something differently in each case.
So i used templates because 99% of the code is the same for both vectors and deques etc.
To specialize:
template<> void mySuperTempalte<std:string>(const std::string myCont)
{
//check type of container
//do something here
}
To specialize for vector:
template<typename C> void mySuperTempalte (std::vector<C> myCont)
{
//check type of container
//do something here
}
To specialize for deque:
template<typename C> void mySuperTempalte (std::deque<C> myCont)
{
//check type of container
//do something here
}
Have you tried a template typename parameter? The syntax is a bit weird because it emulates the syntax used to declare such a container. There's a good InformIT article explaining this in more detail.
template <template <typename> class Container>
void mySuperTemplate(Container<std::string> const& cont) {
}
Notice that you also should declare the argument as a reference!
By the way: this comment
//check type of container
is a dead giveaway that you're doing something wrong. You do not want to check the type of the container. User more sophisticated overloading instead, as shown in sep's answer.
If I am understanding your problem correctly you have an algorithm that will work for STL containers vector, deque etc but are trying to write a template specialisation for string. If this is the case then you can write the generalised templated method that you defined in your question:-
template<typename container> void mySuperTempalte( const container &myCont )
{
// Implement STL container code
}
Then for your string specialisation you declare:-
template<> void mySuperTempalte( const container<std::string> &myCont )
{
// Implement the string code
}
For any other specialisation just change the type declaration for myCont. If you really need to do this for the vector and deque containers then make the template parameter the parameter for the type in that container rather than the container itself as Sep suggested.
template<typename C> void mySuperTempalte( const std::vector<C> &myCont)
{
// check type of container
// do something here
}
It's worth trying to avoid this by making your first implementation work with all STL containers to make your life easier, then you only need the specialisation for the string class. Even consider converting your string to a vector to avoid the specialisation all together.
On a side note, I've changed the container parameter to a const reference, I assume this is what you want, as you declare the object const anyway, this way you avoid a copy.
The answers so far seem helpful, but I think I'd use a different construct. I expect all containers to define value_type, just like the STL containers do. Therefore, I can write
inline template <typename C> void mySuperTemplate (C const& myCont)
{
mySuperTemplateImpl<C, typename C::value_type>(myCont);
}
In general, it's easier to act on a parameter that you've extracted explicitly.
#sep
'Simple' solution
The answer posted by 'sep' is pretty good, probably good enough for 99% of app developers, but could use some improvement if it's part of a library interface, to repeat:
To specialize for vector:
template<typename C> void mySuperTempalte (std::vector<C> myCont)
{
//check type of container
//do something here
}
This will work provided the caller isn't using std::vector. If this works well enough for you, to specialize for vector, list, etc, then stop here and just use that.
More complete solution
First, note that you can't partially specialize function templates -- you can create overloads. And if two or more of them match to the same degree, you will get "ambigous overload" errors. So we need to make exactly one match in every case you want to support.
One technique for doing this is using the enable_if technique -- enable_if allows you to selectively take function template overloads out of the possible match list using an obscure language rule... basically, if some boolean expression is false, the overload becomes 'invisible'. Look up SFINAE for more info if you're curious.
Example. This code can be compiled from the command line with MinGW (g++ parameterize.cpp) or VC9 (cl /EHsc parameterize.cpp) without error:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
template <bool B, class T> struct enable_if {};
template <class T> struct enable_if<true, T> { typedef T type; };
template <class T, class U> struct is_same { enum { value = false }; };
template <class T> struct is_same<T,T> { enum { value = true }; };
namespace detail{
// our special function, not for strings
// use ... to make it the least-prefered overload
template <class Container>
void SpecialFunction_(const Container& c, ...){
cout << "invoked SpecialFunction() default\n";
}
// our special function, first overload:
template <class Container>
// enable only if it is a container of mutable strings
typename enable_if<
is_same<typename Container::value_type, string>::value,
void
>::type
SpecialFunction_(const Container& c, void*){
cout << "invoked SpecialFunction() for strings\n";
}
}
// wrapper function
template <class Container>
void SpecialFunction(const Container& c){
detail::SpecialFunction_(c, 0);
}
int main(){
vector<int> vi;
cout << "calling with vector<int>\n";
SpecialFunction(vi);
vector<string> vs;
cout << "\ncalling with vector<string>\n";
SpecialFunction(vs);
}
Output:
d:\scratch>parameterize.exe calling
with vector<int> invoked
SpecialFunction() default
calling with vector<string> invoked
SpecialFunction() for strings
d:\scratch>
Whether it is a good design or not is left for further discussion. Anyway, you can detect the type of container using partial template specializations. In particular:
enum container_types
{
unknown,
list_container,
vector_container
};
template <typename T>
struct detect_container_
{
enum { type = unknown };
};
template <typename V>
struct detect_container_< std::vector<V> > // specialization
{
enum { type = vector_container };
};
template <typename V>
struct detect_container_< std::list<V> >
{
enum { type = list_container };
};
// Helper function to ease usage
template <typename T>
container_types detect_container( T const & )
{
return static_cast<container_types>( detect_container_<T>::type );
}
int main()
{
std::vector<int> v;
assert( detect_container( v ) == vector_container );
}