Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Can't find overloaded overridden method in base class

45 views
Skip to first unread message

Frederick Gotham

unread,
Mar 26, 2020, 11:30:14 AM3/26/20
to

The following code won't compile for me with GCC 7.4.0.

Here's the output from the compiler:



g++ -std=c++11 test.cpp -o prog

test.cpp: In function ‘int main()’:
test.cpp:80:7: error: no match for call to ‘(Transformer<Monkey>) (std::array<unsigned char, 16>&)’
t(tmp); /* Why can't this find the method in the Base class? */
^
test.cpp:49:7: note: candidate: void Transformer<T>::operator()(const std::array<unsigned char, 16>&, std::array<unsigned char, 16>&) const [with T = Monkey]
void operator()(array<uint8_t,g_BLOCKSIZE> const &inBlock, array<uint8_t,g_BLOCKSIZE> &outBlock) const override
^~~~~~~~
test.cpp:49:7: note: candidate expects 2 arguments, 1 provided



And here's the code:


#include <cstddef>
#include <cstdint>
#include <array>
#include <type_traits>

using std::size_t;
using std::uint8_t;
using std::array;

size_t constexpr g_BLOCKSIZE = 16u;

class Transformer_Abstract {
public:
virtual ~Transformer_Abstract(void) {} /* Keep this virtual in case there's ever a container of pointers */

virtual void operator()(array<uint8_t,g_BLOCKSIZE> const &, array<uint8_t,g_BLOCKSIZE> &) const = 0;

void operator()(array<uint8_t,g_BLOCKSIZE> &block) const
{
(*this)(block,block);
}
};

template<class T>
class Transformer : public Transformer_Abstract {
protected:

bool const _is_forward;
typename std::aligned_union<0,typename T::Encryption,typename T::Decryption>::type _storage;

public:

Transformer(bool const arg_is_forward) : _is_forward(arg_is_forward)
{
if ( _is_forward )
::new(&_storage) typename T::Encryption();
else
::new(&_storage) typename T::Decryption();
}

~Transformer(void) override /* Base class should have a virtual destructor */
{
if ( _is_forward )
reinterpret_cast<typename T::Encryption*>(&_storage)->T::Encryption::~Encryption();
else
reinterpret_cast<typename T::Decryption*>(&_storage)->T::Decryption::~Decryption();
}

void operator()(array<uint8_t,g_BLOCKSIZE> const &inBlock, array<uint8_t,g_BLOCKSIZE> &outBlock) const override
{
static uint8_t const nullblock[16] = {}; /* All zero */

if ( _is_forward )
reinterpret_cast<typename T::Encryption const *>(&_storage)->ProcessAndXorBlock(inBlock.begin(), nullblock, outBlock.begin());
else
reinterpret_cast<typename T::Decryption const *>(&_storage)->ProcessAndXorBlock(inBlock.begin(), nullblock, outBlock.begin());
}
};

void Pineapple(Transformer_Abstract &t)
{
array<uint8_t,g_BLOCKSIZE> tmp;

t(tmp); /* This works fine */
}

struct Monkey {
struct Encryption { void ProcessAndXorBlock(uint8_t const *, uint8_t const *, uint8_t *) const {} };
struct Decryption { void ProcessAndXorBlock(uint8_t const *, uint8_t const *, uint8_t *) const {} };
};

auto main(void) -> int
{
Transformer<Monkey> t(true);

Pineapple(t);

array<uint8_t,g_BLOCKSIZE> tmp;

t(tmp); /* Why can't this find the method in the Base class? */

}



I thought that the method defined in the base class would be found and called? Do I need to use "using" here in the derived class?

Öö Tiib

unread,
Mar 26, 2020, 11:50:28 AM3/26/20
to
Yes. Or to make all overloads in base class virtual.
Otherwise hiding takes place. The keywords like strict
and hiding were proposed into C++11 to make compiler to
lament about that common confusion but were not accepted.
That bear trap into what everyone must fall is there
because C++ is designed to *hate* novices.

Paavo Helde

unread,
Mar 26, 2020, 11:55:17 AM3/26/20
to
On 26.03.2020 17:29, Frederick Gotham wrote:
>
>
> I thought that the method defined in the base class would be found and called? Do I need to use "using" here in the derived class?

Yep, the base class members are hidden by derived class members of the
same name, you need this in the derived class public section:

using Transformer_Abstract::operator();

There are also other problems in the code (mixing up iterators and
pointers).

Frederick Gotham

unread,
Mar 26, 2020, 12:20:16 PM3/26/20
to
Paavo wrote:
> There are also other problems in the
> code (mixing up iterators and pointers).


You don't like how I use the return value from "array::begin(void)" as a pointer to the first element?

Alf P. Steinbach

unread,
Mar 26, 2020, 1:17:31 PM3/26/20
to
It's not necessarily a pointer.

You can convert to pointer by putting `&*` in front.

But I fail to understand the purpose of the low level shenanigans here.
I would guess that things would be much simpler with `std::vector`.

- Alf

Paavo Helde

unread,
Mar 26, 2020, 1:18:44 PM3/26/20
to
Not me - it's the compiler!


1> ]
1>d:\test\consoletestvs2017\consoletestvs2017\main.cpp(55): note: No
user-defined-conversion operator available that can perform this
conversion, or the operator cannot be called
1>d:\test\consoletestvs2017\consoletestvs2017\main.cpp(51): note: while
compiling class template member function 'void
Transformer<Monkey>::operator ()(const std::array<uint8_t,16>
&,std::array<uint8_t,16> &) const'
1>d:\test\consoletestvs2017\consoletestvs2017\main.cpp(75): note: see
reference to class template instantiation 'Transformer<Monkey>' being
compiled
1>d:\test\consoletestvs2017\consoletestvs2017\main.cpp(57): error C2664:
'void Monkey::Decryption::ProcessAndXorBlock(const uint8_t *,const
uint8_t *,uint8_t *) const': cannot convert argument 1 from
'std::_Array_const_iterator<_Ty,16>' to 'const uint8_t *'
1> with
1> [
1> _Ty=uint8_t
1> ]
1>d:\test\consoletestvs2017\consoletestvs2017\main.cpp(57): note: No
user-defined-conversion operator available that can perform this
conversion, or the operator cannot be called





Frederick Gotham

unread,
Mar 27, 2020, 5:59:15 AM3/27/20
to
On Thursday, March 26, 2020 at 3:50:28 PM UTC, Öö Tiib wrote:

> > I thought that the method defined in the base class would be found and called? Do I need to use "using" here in the derived class?
>
> Yes. Or to make all overloads in base class virtual.
> Otherwise hiding takes place.


I tried making it virtual in the base class but it still fails to compile. I'm using GCC 7.4.0.

Try it there on your own compiler.

Bo Persson

unread,
Mar 27, 2020, 6:33:27 AM3/27/20
to
Making "it" virtual is not enough. *All* overloads must be present in
the base class, otherwise declarations in an inner scope (derived class)
hide names in outer scopes (base class).

This is the same mechanism as for names inside functions and namespaces.
Inner declarations of a name hide all declarations of the same name from
outer scopes.


Bo Persson

Cholo Lennon

unread,
Mar 27, 2020, 1:53:50 PM3/27/20
to
On 26/3/20 12:48, Öö Tiib wrote:

> That bear trap into what everyone must fall is there
> because C++ is designed to *hate* novices.
>

I totally agree with you

--
Cholo Lennon
Bs.As.
ARG
0 new messages