I'm trying to write a priority queue for my programming class but continue to get the following errors:
PriorityQueue.cpp:7:1: error: ‘PriorityQueue::PriorityQueue’ names the constructor, not the type
PriorityQueue.cpp:7:1: error: and ‘PriorityQueue’ has no template constructors
I've been at it for several hours now and have no idea whats wrong. Here is the code it is referring to:
template < typename DataType, typename KeyType, typename Comparator >
PriorityQueue<DataType,KeyType,Comparator>
::PriorityQueue<DataType,KeyType,Comparator>( int maxNumber )
: Heap<DataType,KeyType,Comparator>( int maxNumber )
{
}
Try this
template < typename DataType, typename KeyType, typename Comparator >
PriorityQueue<DataType,KeyType,Comparator>
::PriorityQueue( int maxNumber ) // <-- removed unneeded template parameter
: Heap<DataType,KeyType,Comparator>( maxNumber ) // <--- maxNumber should be a parameter to the base class, not a definition.
{
}
Related
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.)
I have a class that takes a size type as a parameter in case one doesn't want to use size_t or another hard coded type which would require casting and checking for overflows.
This class also has some methods taking a second template type :
template< typename SizeType = uint32_t >
class BufferReader
{
SizeType m_nPosition;
template< typename T >
T Read();
}
My problem is, what is the syntax to implement this ?
template< typename SizeType, typename T >
T BufferReader< SizeType >::Read()
{
// ...
}
Which gives me an error :
invalid use of incomplete type 'class core::BufferReader<SizeType>'
Or :
template< typename T >
template< typename SizeType >
T BufferReader< SizeType >::Read()
{
// ...
}
Which gives the same error.
Or anything else ?
Thank you !
Your second example is nearly right, you just need to have the template parameters of the class first and those of the function second:
template< typename SizeType >
template< typename T >
T BufferReader< SizeType >::Read()
{
// ...
}
You almost got it. You have to stack the templates as in the declaration: first the class and then the member.
template < typename SizeT >
template < typename T >
T
BufferReader<SizeT>::Read()
{
return T {};
}
Note that the code can be simplified by defining the function right in the class body but I understand that some people will prefer to separate declaration from definition for aesthetic reasons.
I have written a list-like template class sll (Single Linked List). Now, I am trying to plugin an allocator to it. I have the default allocator, allocator, and a pool based allocator, pool_allocator. These are designed after STL allocator interface, but I need to add the number of elements that the allocator would handle (the max_size) as a template parameter. So, I have done the following.
enum {Default_1 = 16}; // for example
template <typename T, size_t N = Default_1>
struct allocator {
};
enum {Default_2 = 32}; // for example
template <typename T, size_t N = Default_2>
struct pool_allocator {
};
I want to support two kinds if usage by the client:
1. sll<int> == implying ==> sll<int, allocator<int, Default_1> >
2. sll<int, pool_allocator<int, 4096> >
The difficulty I am having is specifying the default allocator in the sll template class. Initially I had
template<typename T, typename Allocator = allocator<T> > class sll { ...};
It works, but the problem is, user can;t specify the capacity of the allocator.
I tried
template<typename T,
typename Allocator = allocator< typename T, size_t N = Default_3> >
class sll { ... };
but I receive the error:
error: template argument 1 is invalid
I tried few other combinations, but none of them worked. At this point, I am out of ideas, and looking for help from the SO community. Any suggestions or pointers are appreciated.
You have to write:
template<typename T,
typename Allocator = allocator<T, Default_3> >
class sll { ... };
Continuing my journey into the world of variadic templates, I encountered another problem.
Assuming the following template class:
template < typename T >
struct foo
{
//default implementation
};
it is possible to partially specialize it for variadic template instantiations like this:
template < template < typename ... > class T, typename ...Args >
struct foo< T< Args... > >
{
//specialized implementation
};
With this, foo< int > will correspond to the default implementation and foo< std::tuple< int, char > > to the specialized implementation.
However, things become more complicated when using several template parameters. For example, if we have the following template class
template < typename T, typename U >
struct bar {};
and we want to partially specialize it as we did for foo, we cannot do
template < template < typename ... > class T, typename ...TArgs,
template < typename ... > class U, typename ...UArgs >
struct bar< T< TArgs... >, U< UArgs... > > {};
//This would correspond to the specialized version with
//T=std::tuple,
//TArgs=int,char
//U=std::tuple,
//UArgs=float
bar< std::tuple< int, char >, std::tuple< float > > b;
Indeed, if I am correct, we can only have one template parameter pack and it must be positioned at the end of the parameter list. I understand why this is mandatory in template declarations, but for certain partial template specialization (like the example above), this should not be an issue.
Is it possible to achieve partial template specialization with multiple template parameter packs?
Edit: Now I feel silly...the code I gave above compiles perfectly (at least with gcc 4.5). The compile error I had was not because of multiple parameter packs, but because of their use as member functions parameters. In the partial specialization of bar, I tried to define a member function that takes both TArgs and UArgs parameters:
template < template < typename ... > class T, typename ...TArgs,
template < typename ... > class U, typename ...UArgs >
struct bar< T< TArgs... >, U< UArgs... > >
{
void method( TArgs... targs, UArgs... uargs ) //compile error here
{
}
};
On the member function declaration, gcc gives me the error
parameters packs must be at the end of the parameter list.
As far as I can tell, the compiler should be able to define the correct member function for a given template instantiation, e.g. bar< std::tuple< int, char >, std::tuple< float > > should contain a member function void method( int, char, float ). Am I doing something wrong? Or am I trying to do something that is not possible? If so, is there a good reason why this is not possible?
Probably this answer won't clear your question directly,
but the following code compiled on ideone(gcc-4.5.1) when I tested.
#include <cstdio>
#include <tuple>
template< class, class > struct S {
S() { puts("primary"); }
};
template<
template< class... > class T, class...TArgs
, template< class... > class U, class...UArgs
>
struct S< T< TArgs... >, U< UArgs... > > {
S() { puts("specialized"); }
};
int main()
{
S< int, int > p; // "primary"
S< std::tuple< int, char >, std::tuple< float > > s; // "specialised"
}
I'm not sure this code is strictly conformant, but
as far as I read N3225 14.5.3, I couldn't find the statement which mentions
that template parameter pack has to be the last template parameter.
Edit:
I reread N3225 and found the following statements:
8.3.5/4 If the parameter-declaration-clause
terminates with an ellipsis or a
function parameter pack (14.5.3), the
number of arguments shall be equal to
or greater than the number of
parameters that do not have a default
argument and are not function
parameter packs.
14.8.2.5/10 [Note: A function parameter pack can only occur at the
end of a
parameter-declarationlist(8.3.5). -end
note]
So, as you mentioned, function parameter pack has to be the last parameter
unfortunately.
A non-template member function of a class template is an ordinary function
for that class when it is instantiated(fully specialized).
So I wish that the code in this question can be compiled logically, as a
special case.
I have a template struct tree_parse_info declared as follows:
template <
typename IteratorT,
typename NodeFactoryT,
typename T
>
struct tree_parse_info
{
// ...
};
The compiler allows the follows code:
tree_parse_info<> m_info;
Why does this code compile even though we do not have default template parameters for the template struct tree_parse_info ?
If the class has been forward declared previously, you won't need to restate the default parameters. For example:
// forward declare only
template <typename T = int, size_t N = 10>
struct array;
// actual definition
template <typename T , size_t N>
struct array
{};
int main(void)
{
array<> a; // uses the defaults it saw in the forward-declaration
}
Look above your actual definition to see if you forward declared it.
By the way, if you give defaults at one place, and differing defaults at another, you'll get a compile error:
template <typename T = int, size_t N = 10>
struct array;
// error: redefinition of default parameter
template <typename T = double , size_t N = 2>
struct array
{};
Try giving the code you showed us defaults that can't possibly accidentally match, like:
struct stupid_special_tag_type_lolroflwat {};
template <
typename IteratorT = stupid_special_tag_type_lolroflwat,
typename NodeFactoryT = stupid_special_tag_type_lolroflwat,
typename T = stupid_special_tag_type_lolroflwat
>
struct tree_parse_info
{
// ...
};
If you get redefinition errors, you know you've given it defaults in some other location.
When I compile your code with g++, I get the following error:
tp.cpp:10: error: wrong number of
template arguments (0, should be 3)
So you must be compiling something other than the code you are showing us.