Domanda

I'm trying to generalize my class using policy-based design, and it seems that gcc doesn't see the implementation of pure virtual functions that are implemented in base classes. Here is an example:

#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;
}

Errors I'm getting are:

..\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;

There are two problem's I don't quite get:

  1. The compiler seems to not consider AccessPolicy< ReturnType >::implementation< DataClass >... to be an implementation of AccessPolicy< ReturnType >::interface... even though the function signatures are exactly the same.
  2. The compiler cannot resolve which operator[] I'm calling even though they all have different arguments an I'm clearly calling the size_t one (numbers cannot be implicitly converted to strings).

Any ideas why is this happening?

My guess is that even though I'm inheriting directly from "interface" and "implementation" the member functions somehow end up in different namespaces. If that's correct, how do I get around this?


EDIT : added the above example stripped of the templates, as per request

#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;
}
È stato utile?

Soluzione

You're struct testImplementation is inheriting from struct testInterface itself inheriting from struct GetByNameInterface which defines an virtual std::string operator[](std::string ) = 0;

Neither testInterface nor testImplementation are defining an override for this virtual, so testImplementation is an abstract structure.

The fact that you're inheriting from another class that has no relation with the previous one but defines the same operator will not help you. You have to implement your method in a hierarchy between your concrete implementation and your abstract interface, not on a side class.

Altri suggerimenti

In order to do that you implementation class must inherit from your interface class, this way implementation will be accepted, but as said before inheriting from an unrelated class that has an implementation for an abstract function, does not mean that implemented function should considered as implementation of abstract function

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top