explicit instantiation of a method is needed with an unknown type

  c++, c++17, crtp, variadic-templates

Consider the following code

template<typename Derived, typename ...T > struct A;

template<whatever>
struct buz
{
    ...
    auto xyz()
    {
        ...
    }
    
    template <typename T>
    auto xyz(int)
    {
        ....
    }
};

        
template<typename Derived, typename ...T > 
struct A<Derived, std::tuple<T...> > : crtp<Derived, A<Derived, std::tuple<T...>>>
{
    
    auto foo()
    {
        return std::make_tuple (Helper<T>(this->derived().something )...);
    }

    void bar()
    {
        auto f = foo();
        auto x = std::get<0>(f).xyz();
        ...
    }
    
    template<typename S>    
    void bar()
    {
        auto f = foo();
        auto x = std::get<0>(f).xyz();
        ...
    }
        
};

template<typename ...T>
class B : public A<B,std::tuple<T...>>
{
    friend A<B,std::tuple<T...>>;
    typedef  A<B,std::tuple<T...>> A;
    ...
    
    B(bool UseBar=true)
    {
        if(UseBar) 
           A::bar();
    ...
    }
};

I’m trying to simplify something more complex, this is yet not that simple, but I still hope I’m not oversimplified it (let me know I will fixadd information), but consider the above is working.

In the following code, I try to instantiate variable number of B‘s, which I put in tuples. Every B initializes everything needed for the task. The new class C never use B::A::bar, instead uses its own version of class A, where it is also need to call to a different, this time templated xyz, but can’t:

template<typename Derived,typename ...T > 
struct A<Derived,Something, std::tuple<T...> >:crtp<Derived, A<Derived, T...>> //here T is also a tuple, i.e. std::tuple<T...> tuple of tuples
{
    
    typedef std::tuple<T...> Ts;
    
    template <std::size_t ... Is>
    auto foo(std::index_sequence<Is...> const&)
    {
        return std::make_tuple (std::get<Is>(this->derived().m_Bs).foo()...);
    }

        
    void bar()
    {
        auto fs = foo();
        auto f0 = std::get<0>(fs);
        auto x = std::get<0>(f0).xyz();                     // OK
        
        using typename S = SomeTemplate<Ts>::S; //in simple words S it uses information from one T
        
        auto x = std::get<0>(f0).xyz<S>();          // error : type name is not allowed
        auto x = std::get<0>(f0).template xyz<S>(); // warning #1017: name following "template" must be a template
        ...
    }
};

template<typename ...T>
class C : public A<C,Something,std::tuple<T...>>//here T is also a tuple, i.e. std::tuple<T...> tuple of tuples
{
    friend A<C,Something,std::tuple<T...>>;
    
    typedef A<C,Something,std::tuple<T...>> A;
    
    typedef typename tuple(B<T>...) Bs;
    Bs m_Bs;
    ...
    
    C():m_Bs(B<T>(false)...)
    {
        A::bar();
    ...
    }
    ...
};

Obviously an explicit instantiation is needed for xyz<S>. However,
the SomeTemplate<T1, T2, ...,Tn>::S needed for T1 uses’T2, …, Tn’,
unknown to A<B,T1> so can’t create a dummy call from inside. Furthermore, A<B,T1>::foo brings an object that involves an incomplete type from Derived, which I didn’t success to get rid off.

Any idea how to get access to that xyx<S> or another solution which won’t require rewriting everything?

Source: Windows Questions C++

LEAVE A COMMENT