c++ - Why substitution fails in this function template? -


i have set of template functions receive index (is int in example) , return value of given type, i've used sfinae separate std::string arithmetic types:

// 1 template <typename t> typename std::enable_if<std::is_arithmetic<t>::value, t>::type t(int) { ... }  // 2 template <typename t> typename std::enable_if<std::is_same<std::string, t>::value, t>::type t(int) { ... }  // 3 template <template <typename ...> class t, typename ... p> t<p ...> t(int) { ... } 

also, there's function receives container , fills using functions above:

template <typename c> c c(int) {     c r{};     std::insert_iterator<c> iterator(r, r.begin());     *iterator = t<typename c::value_type>(0);     return r; } 

the goal of t tell apart numbers , strings, if pair provided (because comes associative container) then, t should split each pair component in 2 different t calls first , second types.

while deserializing non-associative containers works using associative containers compilation fails:

using vi = std::vector<int>; using mii = std::map<int, int>;  auto o = c<vi>(0);  // deserialize vector auto p = c<mii>(0); // deserialize map 

the compilation fails @ point of deserializing 1 element of container:

*iterator = t<typename c::value_type>(0); 

for non-associative containers c::value_type type mets 1 of conditions of first 2 versions of t, associative containers c::value_type pair , should fail versions #1 , #2 of t not #3 version of t function; issue fails 3 of them:

error: no matching function call 't' *iterator = t<typename c::value_type>(0);             ^~~~~~~~~~~~~~~~~~~~~~~~~ note: in instantiation of function template specialization 'c<std::map<int, int>>' requested here auto p = c<mii>(0);          ^ note: candidate template ignored: requirement 'std::is_arithmetic<pair<const int, int> >::value' not satisfied [with t = std::pair<const int, int>] t(int) { ... } ^ note: candidate template ignored: requirement 'std::is_same<std::string, pair<const int, int> >::value' not satisfied [with t = std::pair<const int, int>] t(int) { ... } ^ note: candidate template ignored: invalid explicitly-specified argument template parameter 't' t<p ...> t(int) { ... }          ^ 

apparently compiler complaining of lack of template-template parameters but, if rid of sfinae error vanishes:

template <typename t> t t(int) { return {}; }  template <template <typename ...> class t, typename ... p> t<p ...> t(int) { return {}; }  template <typename c> c c(int) {     c r{};     std::insert_iterator<c> iterator(r, r.begin());     *iterator = t<typename c::value_type>(0);     return r; }  int main() {     using vi = std::vector<int>;     using mii = std::map<int, int>;      auto o = c<vi>(0);     auto p = c<mii>(0);      // print 0     (auto &v : o) std::cout << v << '\n';     // print 00     (auto &v : p) std::cout << v.first << v.second << '\n';      return 0; } 

it looks sfinae forcing template-template parameter required instead of deduced, why happening? how should solve it?

code available in wandbox 三へ( へ՞ਊ ՞)へ ハッハッ.

it looks (from comment , edit), want execute different functions depending on given template parameters. easiest way use class, since classes more flexible regarding specialization. here small example of do:

// initial declaration (without definition), second template // parameter used enable specializations template <class t, class = void> struct deserializer;  // specialization arithmetic types template <class t> struct deserializer<     t, std::enable_if_t<std::is_arithmetic<t>::value>> {      t operator()() const {      } };  // specialization std::string template <> struct deserializer<std::string> {     std::string operator()() const {      } };  // specialization std::pair<u, v>  template <class u, class v> struct deserializer<std::pair<u, v>> {     std::pair<u, v> operator()() const {      } }; 

then in function c:

deserializer<typename c::value_type> ds; *iterator = ds(); 

you can add intermediate generic function if don't want create object of type deserializer each time:

template <class t> t deserialize() {     return deserializer<t>{}(); } 

but think goal here deserialize multiple objects, having functor not bad in case.


why deduction fails in case?

actually, there no deduction here since deduction works arguments , using return type. problem here instantiation of t:

t<std::pair<int, int>> 

...will never match declaration of t:

template <template <class... > class, class... > auto t(); 

because need:

t<std::pair, int, int> 

...to match such template signature. template signature matched using t<typename c::value_type> signature of form:

template <class t, /* */> 

...where /* */ either variadic template parameter (class...), or list of defaulted template parameters (class x = void, int n = 0), or combination of both.


Comments

Popular posts from this blog

angular - Ionic slides - dynamically add slides before and after -

minify - Minimizing css files -

Add a dynamic header in angular 2 http provider -