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