GCC не видит реализацию через множественное наследование

Я пытаюсь обобщить свой класс, используя дизайн на основе политик, и кажется, что gcc не видит реализацию чисто виртуальных функций, которые реализованы в базовых классах. Вот пример:

#include <iostream>

template <typename ReturnValue, template <typename> class... AccessPolicies>
struct testInterface : public AccessPolicies< ReturnValue >::interface...
{

};

template <typename DataClass, typename ReturnValue, template <typename> class... AccessPolicies>
struct testImplementation :   public DataClass,
public testInterface< ReturnValue, AccessPolicies... >,
public AccessPolicies< ReturnValue >::template implementation< DataClass >...
{

};

template < typename ReturnValue >
struct GetByIndex;

template <>
struct GetByIndex< std::string >
{
class interface
{
public:
virtual std::string operator[](size_t ) = 0;
protected:
virtual ~interface() = default;
};

template <class DataClass>
class implementation
{
public:
virtual std::string operator[](size_t )
{
return "test by index";
}
protected:
virtual ~implementation() = default;
};
};

template < typename ReturnValue >
struct GetByName;

template <>
struct GetByName< std::string >
{
class interface
{
public:
virtual std::string operator[](std::string ) = 0;
protected:
virtual ~interface() = default;
};

template <class DataClass>
class implementation
{
public:
virtual std::string operator[](std::string )
{
return "test by string";
}
protected:
virtual ~implementation() = default;
};
};

struct data
{

};

int main()
{
testImplementation< data, std::string, GetByIndex, GetByName> test;
testInterface< std::string, GetByIndex, GetByName >& Test = test;

std::cout << Test[5] << std::endl;

return 0;
}

Я получаю следующие ошибки:

..\nienazwany\main.cpp: In function 'int main()':
..\nienazwany\main.cpp:78:67: error: cannot declare variable 'test' to be of abstract type 'testImplementation<data, std::basic_string<char>, GetByIndex, GetByName>'
testImplementation< data, std::string, GetByIndex, GetByName> test;
^
..\nienazwany\main.cpp:10:8: note:   because the following virtual functions are pure within 'testImplementation<data, std::basic_string<char>, GetByIndex, GetByName>':
struct testImplementation :   public DataClass,
^
..\nienazwany\main.cpp:53:29: note:     virtual std::string GetByName<std::basic_string<char> >::interface::operator[](std::string)
virtual std::string operator[](std::string ) = 0;
^
..\nienazwany\main.cpp:26:29: note:     virtual std::string GetByIndex<std::basic_string<char> >::interface::operator[](size_t)
virtual std::string operator[](size_t ) = 0;
^
..\nienazwany\main.cpp:81:24: error: request for member 'operator[]' is ambiguous
std::cout << Test[5] << std::endl;
^
..\nienazwany\main.cpp:53:29: note: candidates are: virtual std::string GetByName<std::basic_string<char> >::interface::operator[](std::string)
virtual std::string operator[](std::string ) = 0;
^
..\nienazwany\main.cpp:26:29: note:                 virtual std::string GetByIndex<std::basic_string<char> >::interface::operator[](size_t)
virtual std::string operator[](size_t ) = 0;

Есть две проблемы, которые я не совсем понимаю:

  1. Компилятор, кажется, не считает AccessPolicy< ReturnType >::implementation< DataClass >... быть реализацией AccessPolicy< ReturnType >::interface... хотя сигнатуры функций абсолютно одинаковы.
  2. Компилятор не может определить, какой оператор [] я вызываю, даже если у них всех разные аргументы и я явно вызываю size_t (числа не могут быть неявно преобразованы в строки).

Есть идеи, почему это происходит?

Я предполагаю, что, хотя я наследую напрямую от «интерфейса» и «реализации», функции-члены каким-то образом оказываются в разных пространствах имен. Если это правильно, как мне обойти это?


РЕДАКТИРОВАТЬ : добавил приведенный выше пример без шаблонов, согласно запросу

#include <iostream>

class GetByIndexInterface
{
public:
virtual std::string operator[](size_t ) = 0;
protected:
virtual ~GetByIndexInterface() = default;
};

class GetByIndexImplementation
{
public:
virtual std::string operator[](size_t )
{
return "test by index";
}
protected:
virtual ~GetByIndexImplementation() = default;
};class GetByNameInterface
{
public:
virtual std::string operator[](std::string ) = 0;
protected:
virtual ~GetByNameInterface() = default;
};

class GetByNameImplementation
{
public:
virtual std::string operator[](std::string )
{
return "test by string";
}
protected:
virtual ~GetByNameImplementation() = default;
};

struct data
{

};

struct testInterface : public GetByIndexInterface,
public GetByNameInterface
{

};

struct testImplementation :   public data,
public testInterface,
public GetByIndexImplementation,
public GetByNameImplementation
{

};

int main()
{
testImplementation test;
testInterface& Test = test;

std::cout << Test[5] << std::endl;

return 0;
}

0

Решение

Вы struct testImplementation наследуется от struct testInterface сам по себе наследует от struct GetByNameInterface который определяет virtual std::string operator[](std::string ) = 0;

ни testInterface ни testImplementation определяем переопределение для этого виртуального, так testImplementation это абстрактная структура.

Тот факт, что вы наследуете от другого класса, который не имеет отношения к предыдущему, но определяет тот же operator не поможет тебе. Вы должны реализовать свой метод в иерархии между вашей конкретной реализацией и вашим абстрактным интерфейсом, а не на стороне класса.

1

Другие решения

Для этого вам implementation класс должен наследовать от вашего interface класс, таким образом, реализация будет принята, но, как сказано выше, наследование от несвязанного класса, имеющего реализацию для абстрактной функции, не означает, что реализованная функция должна рассматриваться как реализация абстрактной функции.

0

По вопросам рекламы [email protected]