1

I have the following problem( see code below).

In a class that inherits from a base class, I want to be able to have two implementations of operator(). One that takes integers, one that takes "indices", see simple Index class. The operator(ints...) will be in the child class, while I need to have the operator(Index...) in the parent class (also with different return type.)

The code below is not the exact design but a minimal working example explaining the final problem.

Problem is, if I put operator(Index...) in the child class, everything is good. If I put it in the base class, i get a compilation error:

error: no match for call to ‘(Tensor<1, int>) (Index<'i'>&)’

when I call vec(i) and the end of the main(). I understand the compiler doesn't find the good method, but why ? Is there some "shadowing" rule associated to variadic templates ?

Thanks !

#include <iostream>
#include <type_traits>

template<char i>
class Index{
public:
    Index(){};
};

template<int order, typename T, class tensor_type>
class Tensor_traits{
  public:

      //// here, doesn't compile ! !
    //template <char i>
    //T&operator()(Index<i> &ii){
    //std::cout << "puet" << std::endl;
    //}
};


template<int order, typename T>
class Tensor : public Tensor_traits<order, T, Tensor<order, T>> {
    private:
    int data[3] = {1,2,3};
    public:
    Tensor(){};

    template <typename... Idx>
        typename std::enable_if<std::is_same<Idx...,int>::value
        or std::is_same<Idx...,unsigned int>::value
        or std::is_same<Idx...,size_t>::value, T&>::type
        operator()(const Idx&... idx){
        return data[0]; //dummy here, actually i do other stuff !
        }

    // here, works!
    template <char i>
        T&operator()(Index<i> &ii){
        std::cout << "puet" << std::endl;
        }

};


int main() {

    Tensor<1,int> vec1;

    std::cout<< vec1(1) << std::endl;;

    Index<'i'> i;

    vec1(i);
}

1 Answer 1

2

Try adding

using Tensor_traits<order, T, Tensor<order, T>>::operator();

or (suggested by Yakk (thanks) to have Base for other uses)

using Base = Tensor_traits<order, T, Tensor<order, T>>;
using Base::operator();

in Tensor

The problem isn't that the base class is a template class; the problem is that the derived class define another operator() method function that hide the operator() method inherited.

To verify this, delete the operator() defined in the derived class and you can see that, also without using, you can use the operator() of the base class.

Using using unhide the operator() of the base class, when an operator() is defined in the derived class, so you can use both.

Sign up to request clarification or add additional context in comments.

4 Comments

Myself, I'd first do using Base=Tensor_traits<order, T, Tensor<order, T>>; then using Base::operator();. Because my brain isn't smart enough to instantly prove Tensor_traits<order, T, Tensor<order, T>> is just the base of Tensor<order,T>, and by naming it Base the intention is more clear.
@Yakk - also to avoid code duplication in case of using for multiple base methods?
and in constructors etc. If it wasn't CRTP, what I usually do is do that within the template arguement list as ,class Base = Tensor_traits<order, T, Tensor<order, T>>, but with CRTP that doesn't work.
Thanks, it does work. But why does it hide it ? The arguments are different. I had tried to delete the operator() in the derived class and saw it was correctly calling for the one in the base class, but still ?

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.