简体   繁体   中英

Can't deduce template parameter when helper template struct is used

I would like to make some template functions work with existing template-struct helpers. However template argument deduction fails. Is there a work-around?

Example

This overloaded operator << compiles and works:

template <typename T>
inline typename std::vector<T>&
operator<<(
    typename std::vector<T>& vec,
    const typename std::vector<T>::value_type& val)
{
    vec.push_back(val);
    return vec;
}

But when I try to use a helper struct this doesn't compile:

template<typename T>
struct Vector
{
    typedef std::vector<T> Type;
};

template <typename T>
inline typename Vector<T>::Type&
operator<<(
    typename Vector<T>::Type& vec,
    const typename Vector<T>::Type::value_type& val)
{
    vec.push_back(val);
    return vec;
}

gcc error:

error: no match for 'operator<<' (operand types are 'std::vector<int>' and 'int')
    ...
note: candidate: 
'template<class T> typename Vector<T>::Type& operator<<
(typename Vector<T>::Type&, const typename Vector<T>::Type::value_type&)'
 operator<<(
 ^~~~~~~~
note:   template argument deduction/substitution failed:
note:   couldn't deduce template parameter 'T'

clang error:

error: invalid operands to binary expression ('std::vector<int>' and 'int')
   vec << int(2);
   ~~~ ^  ~~~~~~
note: candidate template ignored: couldn't infer template argument 'T'
operator<<(
^

Live example

Question

  • What prevents a successful template parameter deduction in this case?
  • Is there a c++03 work-around for this case? Alias templates would solve the problem in c++11 .

Note: In my real problem second parameter is not necessarily T and I can't use it to deduce vector type.

Note 2: the real helper struct contains some platform specific pre-processing and looks something like:

template <class T>
struct Helper
{
#if defined(_WIN32_WCE)
    typedef std::vector<T, WMHeapAllocator<T> > Vector;  
#else
    typedef std::vector<T> Vector;      
#endif
};

This is a Non-deduced contexts , which is not restricted to C++03. See my previous answer Template parameter cannot be deduced .

As for a workaround, you need to make one of the argument in the function where T can be deduced. Once it is deduced from one place, compiler will use it in other places.

In your case, if you can be sure that value_type will be T , then use this will work:

template <typename T>
inline typename Vector<T>::Type&
operator<<(
    typename Vector<T>::Type& vec,
    const T& val)
{
    vec.push_back(val);
    return vec;
}

Here T is deduced from second argument, and used in the first.

EDIT ( to reflect the edit of question )

You don't need a helper class, a template template solution might be better:

template<template<typename, typename> class Container, class T, class U>
inline Container<T, U>&
operator<<(
        Container<T, U>& vec,
        const typename Container<T, U>::value_type& val)
{
    vec.push_back(val);
    return vec;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM