I have two templates
template< template <class T> class ALLOCATOR = std::allocator >
class Foobar final
{
public:
struct Entry
{
int foo;
int bar;
};
using Allocator = ALLOCATOR<Entry>;
using Container = std::vector< Entry, Allocator >;
Container contents;
};
namespace Snafu
{
template <class T >
class Allocator
{
using pointer = T*;
};
}
Later on in some test code this is instantiated as:
Allocator<Foobar::Entry> allocator(counter);
I wish to add another parameter to the second template thus:
template <class T, class Ptr = T* >
class Allocator
{
using pointer = Ptr;
};
But this results in the following cryptic error for the previous instantiation:
FooTest.cpp:79:35: error: type/value mismatch at argument 1 in template parameter list for template<template<class T> class ALLOCATOR> class Foobar
Allocator<Foobar<Allocator>::Entry> allocator(counter);
^
FooTest.cpp:79:35: note: expected a template of type template<class T> class ALLOCATOR, got template<class T, class PTR> class Snafu::Allocator
FooTest.cpp:79:43: error: template argument 1 is invalid
Allocator<Foobar<Allocator>::Entry> allocator(counter);
^
FooTest.cpp:79:43: error: template argument 2 is invalid
FooTest.cpp:79:62: error: cannot convert Snafu::SnafuCountingAllocator to int in initialization
Allocator<Foobar<Allocator>::Entry> allocator(counter);
^
FooTest.cpp:80:25: error: type/value mismatch at argument 1 in template parameter list for template<template<class T> class ALLOCATOR> class Foobar
If we take the analogy of a function. If I add a new parameter with a default value. I can still invoke it exactly as before. Why does this not apply for this C++ template?
The obvious culprit is the 'self' referential type:
Allocator<Foobar<Allocator>::Entry> allocator(counter);
Somehow for the first case Allocator can be deduced but simply adding a default parameter breaks this.
Why? I think it may be more proper to invert the question. How did this work before I added the parameter?
What is the fix?
I have a suspicion it relates to my other question and Re: Ext pointer vs N2913. Perhaps I need to implement some kind of 'rebind' thingamy.
As pointed out in the comments the problem is there is one temlate parameter here:
template <class T> class ALLOCATOR
I have broken things by adding a new parameter to my Allocator class. So it is no longer compatible with the template.
Also std::allocator takes exactly one template parameter.
Some template-fu is necessary to solve this.