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
Post a Comment