0

I have a Host with 2 policies, each of which with a print function. If I call Policy::print(), there's no problem, but if I call OtherPolicy::print() then I get an error.

Error   C2352    'OtherPolicy<T,Host<T,SubPolicy,OtherPolicy>>::printer': illegal call of non-static member function
        with
        [
            T=uint32_t
        ]   Scratch D:\tmp\ScratchCpp\Scratch\Scratch\HostPolicy.h  63  
#include <iostream>

template<
    typename T,
    class Host
>
class Policy {
public:
    virtual void printer()
    {
        std::cout << "base policy" << std::endl;
    }
};

template<
    typename T,
    class Host
>
class SubPolicy : Policy<T, Host> {
public:
    void printer() override
    {
        auto host = static_cast<Host&>(*this);
        std::cout << "sub policy" << std::endl;
    }
};

template<
    typename T,
    class Host
>
class OtherPolicy {
public:
    void printer()
    {
        auto host = static_cast<Host&>(*this);
        std::cout << "other policy" << std::endl;
    }
};

template<
    typename T,
    template<typename, class> class A,
    template<typename, class> class B
>
class Host :
    public A<T, Host<T, A, B>>,
    public B<T, Host<T, Policy, B>> {
public:
    void printer()
    {
        std::cout << "host" << std::endl;
        A<T, Host>::printer();
        B<T, Host>::printer(); // comment out this line to compile successfully
    }
};

int main(int argc, char **argv)
{
    Host<uint32_t, SubPolicy, OtherPolicy> host;
    host.printer();
}

Would someone be so kind as to explain what's going on and how to do this properly?

1
  • 1
    If you have several such calls in your code then I'd suggest a readability typedef, e.g. using ParentB = B<T, Host<T, Policy, B>>; in the private section, and then the call would be ParentB::printer(); Commented Jul 4, 2019 at 3:53

1 Answer 1

2

The second base class for Host is of type B<T, Host<T, Policy, B>>, not B<T, Host>. This results in the error, because B<T, Host> is not a base class of Host.

The fix is to properly name the type of the base class:

B<T, Host<T, Policy, B>>::printer();
Sign up to request clarification or add additional context in comments.

2 Comments

Interesting! Why do I need to fully declare the parameters for Host for B but not for A?
@calben When you specify Host in A<T, Host> from within the Host class declaration, it is referring to the class being declared (just like you can declare constructors with just Host without repeating the types). This will use the same template parameters as if you specified Host<T, A, B>. Since the base class B uses a different class for the second template parameter of Host, you need to specify them when you access the class. Otherwise you end up with B<T, Host<T, A, B>>.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.