Domanda

I'm trying to recursivly traverse my templated structure.
To do this, I write recursive function get_my. It returns i-th element of chained my_pair's.
get_my may be element Type, or pair type.

#include <iostream>
#include <string>
#include <vector>

using namespace std;


template<typename T0, typename T1>
struct my_pair{
    my_pair(T0 el0, T1 el1): el0(el0), el1(el1) {}
    T0 el0;
    T1 el1; // may be next pair
};

///
/// ERROR occurs here!
///
template<typename PairT>
auto get_my(PairT p, int i,  int current = 0) -> decltype( current == i ? p.el0 : p.el1 ){
    if (current == i){
        return p.el0;
    } else {
        return get_my(p.el1, i, current++);
    } 
}

template<typename T0, typename T1>
my_pair<T0, T1> make_my_pair(T0 el0, T1 el1){
    return my_pair<T0, T1>(el0, el1);
}



int main()
{
    my_pair<double, double> p1(12.789, 12.66);
    //auto p1 = make_my_pair(12.46, 12.66);
    //auto p2 = make_my_pair(p1, 12.66);

    auto el = get_my(p1, 0);
    cout<< el;
    return 0;
}

So... the compilers says:

main.cpp:19:18: error: request for member 'el0' in 'p', which is of non-class type 'double'
         return p.el0;
                  ^
main.cpp:21:42: error: request for member 'el1' in 'p', which is of non-class type 'double'
         return get_my(p.el1, i, current++);

And I really don't understand why. It seems it try to traverse farther then it should.

È stato utile?

Soluzione

Even when the compiler knows that the else block won't be entered, the code inside it must be syntactically valid. Consider what happens here when p is double:

if (current == i){
    return p.el0;
} else {
    return get_my(p.el1, i, current++);
}

get_my gets instantiated and inside it the compiler sees return p.e10 with Pair being double.

The solution is overloading. Write another overload of my_get that stops the recursion when Pair is deduced for something else than my_pair. This can be done with enable_if idiom for example.

Even better, you could have an overload with my_pair<T1, T2> that recurses, and another general template that does not. No enable_if needed.

Altri suggerimenti

You're trying to specify the return type, based on current == i ? type1 : type2 which is your issue.

The return type should be known in compile-time. In your case decltype is returning double as type, then you're trying to call .el0 method of that primitive type.

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