【问题标题】:Can't deduce template parameter when helper template struct is used使用辅助模板结构时无法推断模板参数
【发布时间】:2023-03-07 19:02:01
【问题描述】:

我想让一些模板函数与现有的模板结构助手一起工作。但是模板参数推导失败。有解决办法吗?

示例

这个重载的operator << 编译并工作:

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;
}

但是当我尝试使用帮助器 struct 时,这不会编译:

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: 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: 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

问题

  • 在这种情况下,是什么阻止了成功的模板参数推导?
  • 是否有针对这种情况的c++03 解决方法?别名模板将解决c++11 中的问题。

注意:在我的实际问题中,第二个参数不一定是T,我不能用它来推断向量类型。

注意 2: 真正的辅助结构包含一些特定于平台的预处理,看起来像:

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

【问题讨论】:

  • C&lt;T&gt;::Type 中,T 是不可演绎的(我们可能有(在一般情况下)几个匹配的T)。 (在第一个带有::value_type 的sn-p 中也是如此,所以T 仅从第一个参数推导出来)。

标签: c++ c++03 template-argument-deduction


【解决方案1】:

这是一个非推导上下文,它不限于 C++03。看我之前的回答Template parameter cannot be deduced

作为一种解决方法,您需要在函数中创建一个参数,其中T 可以推导出来。一旦从一个地方推导出来,编译器就会在其他地方使用它。

在您的情况下,如果您可以确定 value_type 将是 T,那么使用它会起作用:

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

这里T是从第二个参数推导出来的,并在第一个参数中使用。

EDIT(反映问题的编辑)

您不需要帮助类,模板模板解决方案可能会更好:

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;
}

【讨论】:

  • 不幸的是,在我的实际问题中,第二个参数不一定连接到T。我已经更新了答案。
  • 也许您可以尝试使用模板模板参数,而不是辅助类。
  • 啊哈,这很聪明。那么你建议做类似this 的事情吗?
  • 查看我的更新答案。事实上,如果它的唯一目的是存储内部类型的编译时间信息,你就不需要这个帮助类。你的代码不会编译,因为它仍然是一个非推断的上下文。
  • But this does compile。同意在这种情况下我不需要模板函数中的帮助器。
猜你喜欢
  • 2020-07-01
  • 1970-01-01
  • 2013-02-18
  • 1970-01-01
  • 2017-03-22
  • 2010-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多