0

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.

Bruce Adams
  • 4,953
  • 4
  • 48
  • 111

0 Answers0