c++ - Variadic templates with defaulted parameters -
first background. origin of question (and source of immense frustration me right now) i'm trying libc++ usable msvc. compiling library didn't prove tricky, getting templates compile is.
one big hurdle i've hit trying compile headers variadic templates enabled. specifically, in header there code templated __invoke functions (for generically invoking function types variadic parameters).
i've extracted of code provide stand alone snippet. myinvoke templates based on __invoke ones in libc++. comments in code explain what's going on (apologies, not small snippet!):
#include <type_traits> using namespace std; // declarations of myinvoke templates. both of them designed take // member function pointer _fp, class instance _a0 (which _fp assumed // point member of) , variadic list of arguments _fp. // first 1 handles case _a0 instance of class // derived class _fp member of. // second 1 handles case when _a0 pointer instance of // class derived class _fp member of. template <class _fp, class _a0, class ..._args, class = typename enable_if < is_member_function_pointer<typename remove_reference<_fp>::type>::value && is_base_of<typename remove_reference<typename __member_pointer_traits<typename remove_reference<_fp>::type>::_classtype>::type, typename remove_reference<_a0>::type>::value >::type > auto myinvoke(_fp&& __f, _a0&& __a0, _args&& ...__args) -> decltype((std::forward<_a0>(__a0).*__f)(std::forward<_args>(__args)...)); template <class _fp, class _a0, class ..._args, class = typename enable_if < is_member_function_pointer<typename remove_reference<_fp>::type>::value && !is_base_of<typename remove_reference<typename __member_pointer_traits<typename remove_reference<_fp>::type>::_classtype>::type, typename remove_reference<_a0>::type>::value >::type > auto myinvoke(_fp&& __f, _a0&& __a0, _args&& ...__args) -> decltype(((*std::forward<_a0>(__a0)).*__f)(std::forward<_args>(__args)...)); // definitions of myinvoke templates. template <class _fp, class _a0, class ..._args, class> inline auto myinvoke(_fp&& __f, _a0&& __a0, _args&& ...__args) -> decltype((std::forward<_a0>(__a0).*__f)(std::forward<_args>(__args)...)) { return (std::forward<_a0>(__a0).*__f)(std::forward<_args>(__args)...); } template <class _fp, class _a0, class ..._args, class> inline auto myinvoke(_fp&& __f, _a0&& __a0, _args&& ...__args) -> decltype(((*std::forward<_a0>(__a0)).*__f)(std::forward<_args>(__args)...)) { return ((*std::forward<_a0>(__a0)).*__f)(std::forward<_args>(__args)...); } // class member can create member fn pointer to. struct someclass { typedef double(someclass::*foo_t)(int, float, double); double foo(int a, float b, double c){return 0.0;} }; int main() { someclass sc; someclass::foo_t pfoo = &someclass::foo; // invoke first template myinvoke(pfoo, sc, 0, 0.0f, 0.0); // invoke second template. myinvoke(pfoo, &sc, 0, 0.0f, 0.0); return 0; }
this code compiles fine gcc, fails msvc (using either libc++ or msvc's type_traits header). i'll come onto error in moment, first need clear points on templating.
question 1:
can point me specific part of standard specification, specific documentation or give me official lingo trick of defaulting parameter after parameter pack.
question 2:
how compiler pick correct definition (implementation) of template? clear me how correct declaration chosen sfinae means 1 can work. however, definitions indistinguishable apart trailing return type. sfinae apply in scope of trailing return types? if that's case of course only 1 of decltype statements can compile 1 implementation applicable (in context of each myinvoke call). however, still strange (to me @ least) compiler need instanciate both definitions of template - 1 each call of myinvoke. each 1 have same signature return types same in both cases (although resolved in different way). mean compiler sees these 2 instances of template different? if so, can point me documentation of please?
onto msvc error
1>test.cpp(165): warning c4348: 'myinvoke' : redefinition of default parameter : parameter 4
1> test.cpp(162) : see declaration of 'myinvoke'
1>test.cpp(196): error c2995: 'unknown-type myinvoke(_fp &&,_a0 &&,_args &&...)' : function template has been defined
1> test.cpp(162) : see declaration of 'myinvoke'
1>test.cpp(211): error c3861: 'myinvoke': identifier not found
1>test.cpp(214): error c3861: 'myinvoke': identifier not found
(to appropriate line numbers match up, copy paste sample into: http://webcompiler.cloudapp.net/)
it's probable clear answer question 1 me solve problem but:
question 3:
what part of msvc non-conformance causing this? indeed non-conformance or possibly case gcc/clang support extensions language?
thanks in advance. i'm off coffee , pretend templates don't exist (this tip of iceberg in terms of "fun" i'm having!).
Comments
Post a Comment