0

I try to create a framework that allows developers to write handlers on different levels of abstraction. Therefore I try to write a base handler, that has the less abstract interface and calls the derived handler with a more abstract interface and the default operations like e.g. this:

template<typename Derived>
struct base {
    template<typename A>
    int operator () (int x, A& a) {
        return (*reinterpret_cast<Derived*>(this))(x) + a;
    }
};

The derived handler should only have to implement the simple interface:

struct derived: public base<derived> {
    int operator () (int x) { return x; }
};

But when I use it like this:

int main(int, char**) {
    derived d;
    std::cout << d(1, 2) << std::endl;
}

I get the folowing output from g++ -c -Wall -Werror test2.cpp (gcc version is 5.3.1):

test2.cpp: In function 'int main(int, char**)':
test2.cpp:18:24: error: no match for call to '(derived) (int, int)'
     std::cout << d(1, 2) << std::endl;
                        ^
test2.cpp:12:9: note: candidate: int derived::operator()(int)
     int operator () (int x) { return x; }
         ^
test2.cpp:12:9: note:   candidate expects 1 argument, 2 provided

I also tried with clang vresion 3.8.0 (clang++ -c -Wall -Werror test2.cpp) with a similar result:

test2.cpp:18:18: error: no matching function for call to object of type 'derived'
    std::cout << d(1, 2) << std::endl;
                 ^
test2.cpp:12:9: note: candidate function not viable: requires single argument 'x', but 2 arguments were provided
    int operator () (int x) { return x; }
        ^
1 error generated.

The call operator template in the base class is not considered. I have also tried to use a different method name, because maybe operators are somehow special, but that did not help as well. What can I do to create such and interface?

Of course I'd like to avoid to have to implement the call operator template with two operands in the derived class, because the derived class is, what the user of the framework is supposed to provide and I want to make his life as easy as possible.

cdonat
  • 2,748
  • 16
  • 24
  • If you write essentially the same code as a class rather than a template you'll get the same problem. – Pete Becker May 08 '16 at 16:58
  • The `operator()` in the derived class hides all functions named `operator()` of the base class. Add a `using base::operator();` in the derived class to "unhide" the base class's `operator()`; this enables overloading between those two functions. – dyp May 08 '16 at 16:58
  • Notice that @dyp solution will not let your code compile yet because of another problem: you are trying to create a non-const reference to r-value (literal 2) – Revolver_Ocelot May 08 '16 at 17:04
  • Thanks a lot to all of you. My Bad, that I didn't find the answer myself. @dyp yes, that is the solution. – cdonat May 09 '16 at 08:27
  • @Revolver_Ocelot good catch, though that is only an issue with the minimal example here, not with my framework. – cdonat May 09 '16 at 08:27

0 Answers0