Search code examples
c++c++11metaprogrammingenable-iftemplate-function

Critical order of enable_if template functions


Why is it important to the compiler to have the following order of definition for a visitor of a std::tuple

namespace TupleVisit{

        //This function SHOULD BE DEFINED SECONDLY; 
        //IN THIS CONFIGURATION COMPILER DOES NOT 
        //SEE THE BELOW RECURSTION TERMINATION ???
        template<std::size_t Idx = 0,
                 typename Visitor,
                 typename... T,
                 typename std::enable_if< Idx < sizeof...(T) , void *>::type = nullptr
                 >
        static
        void visit(Visitor && v, std::tuple<T...>  & t){
            v( std::get<Idx>(t) );
            TupleVisit::visit<Idx+1, Visitor, T... >(std::forward<Visitor>(v),t);
        }


        template<std::size_t Idx = 0,
                 typename Visitor,
                 typename... T,
                 typename std::enable_if< Idx == sizeof...(T) , void *>::type = nullptr
                  >
        static void
        visit(Visitor && v, std::tuple<T...> & t){}
}

Live example : Code

I think the general rule for multiple enable_if switches should be to prototype all functions and then define them in any order? Will that result in always seeing the correct available function by SFINAE?


Solution

  • Why would it see the visit declared below it?

    template functions are not macros -- function lookup is done at the point the template is written, plus ADL lookup from the context where the template is called.

    As the second visit cannot be found via ADL, it is not visible at the point of call within the first visit.