【问题标题】:Why isn't template argument deduction working?为什么模板参数推导不起作用?
【发布时间】:2015-10-06 09:17:26
【问题描述】:

以下玩具程序将一种音乐类型转换为相应的颜色。它编译和执行得很好——COUNTRY 的转换失败,正如预期的那样,conversion() 函数返回默认值,WHITE。但是,如果我删除模板参数<MUSIC, COLOR>,模板参数推导无法识别要使用的类型。我怎样才能让扣除工作?

#include <map>
#include <iostream>
#include "boost/assign.hpp"

template<typename Key, typename T>
T convert(const Key &k, const T &d, const std::map<Key, T> &m) {
    typename std::map<Key, T>::const_iterator it = m.find(k);
    return it == m.end() ? d : it->second;
}

enum MUSIC { ROCK, RAP, EDM, COUNTRY };
enum COLOR { RED, BLUE, ORANGE, WHITE };

int main()
{
    COLOR c = convert<MUSIC, COLOR>(COUNTRY, WHITE,
        boost::assign::map_list_of (RAP, RED) (EDM, BLUE) (ROCK, RED));
    std::cout << c << std::endl;
}

【问题讨论】:

  • 如果您也为地图类型添加模板参数会怎样?
  • template

标签: c++ templates boost assign template-argument-deduction


【解决方案1】:

boost::assign::map_list_of 可能不是map&lt;K,V&gt; 类型,而是某种可转换为它的类型。

编译器试图从前 2 个参数和最后一个参数中推断出类型。最后一个 1 没有意义,所以它放弃了。

我们可以阻止对最后一个参数的推导如下:

template<class T>struct tag{using type=T;};
template<class Tag>using type_t=typename Tag::type;

template<class T>using block_deduction=type_t<tag<T>>;

template<typename Key, typename T>
T convert(const Key &k, const T &d, const block_deduction<std::map<Key, T>> &m) {
  typename std::map<Key, T>::const_iterator it = m.find(k);
  return it == m.end() ? d : it->second;
}

鲍勃应该是你的叔叔。

在 C++03 中:

template<class T>struct no_deduction{typedef T type;};

template<typename Key, typename T>
T convert(const Key &k, const T &d, const typename no_deduction<std::map<Key, T>>::type &m) {
  typename std::map<Key, T>::const_iterator it = m.find(k);
  return it == m.end() ? d : it->second;
}

这在逻辑上是等价的,但是更丑。

【讨论】:

  • 确实是assign_detail::generic_list&lt;std::pair&lt;...&gt;&gt;
  • coliru 说:'boost::assign_detail::generic_list&lt;std::pair&lt;MUSIC, COLOR&gt; &gt;' is not derived from 'const std::map&lt;Key, T&gt;' boost::assign::map_list_of (RAP, RED) (EDM, BLUE) (ROCK, RED));
  • @Barry aka,auto 被发明的原因。
  • @Yakk 哦,当然。只是对你的第一句话进行确认(好像你需要它)
  • @Yakk @NathanOliver 哦,忘了说我想要一个 C++03 解决方案,所以 auto 和初始化列表已经出来了。
【解决方案2】:

正如Yakkhis answer 中提到的boost::assign::map_list_of 不是std::map,但它可以转换为1。如果不想更改您的功能,您可以更改创建地图的方式。使用 C++,我们现在有了initializer list,它可以用来构造一个对象。使用初始化列表我们可以改变

COLOR c = convert<MUSIC, COLOR>(COUNTRY, WHITE,
    boost::assign::map_list_of (RAP, RED) (EDM, BLUE) (ROCK, RED));

COLOR c = convert(COUNTRY, WHITE, {{RAP, RED},{EDM, BLUE},{ROCK, RED}});

这将给出相同的结果并允许模板类型推导工作。

Live Example

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-19
    • 2021-12-06
    • 1970-01-01
    • 2011-08-28
    • 1970-01-01
    • 2017-07-03
    相关资源
    最近更新 更多