【问题标题】:Template function overloading (generic type vs template template type) choose correct overload模板函数重载(泛型与模板模板类型)选择正确的重载
【发布时间】:2017-08-07 14:44:15
【问题描述】:

我有一个模板函数,只要模板类型是数字,它就会对给定的值做一些事情:

template <typename scalar_t>
void function(scalar_t value)
{
    if constexpr (std::is_floating_point_v<scalar_t>)
    {
        std::cout << value << 'F';
    }
    if constexpr (std::is_integral_v<scalar_t>)
    {
        std::cout << value;
    }
}

这个模板的重载需要一个包含数字的容器:

template <typename scalar_t, template <typename> class container_t>
void function(const container_t<scalar_t> &container)
{
    for (const auto &value : container)
    {
        function(value);
        std::cout << ' ';
    }
}

使用上面的模板,我调用以下代码:

int main()
{
    function('0');
    function(short{1});
    function(2);
    function(3l);
    function(4ll);
    function(5.f);
    function(6.);

    std::vector<int> v{7, 8, 9, 10};
    std::list<double> l{11., 12., 13., 14.};

    function(v);
    function(l);

    return 0;
}

它给出以下输出:

012345F6F

虽然我期待以下输出:

012345F6F7 8 9 10 11F 12F 13F 14F 

这意味着选择了第一个模板版本 (function(scalar_t value)) 而不是第二个版本 (function(const container_t&lt;scalar_t&gt; &amp;container))。

如何强制为模板模板参数选择模板函数的第二个版本?

【问题讨论】:

  • 不确定是否是问题所在,但vectorlist 没有一个,而是两个模板参数
  • @tobi303 that was the problem indeed 如果你能在答案中解释为什么我可以投票:)

标签: c++ templates overloading


【解决方案1】:

这里的问题是您的模板类型不匹配。 std::vectorstd::list 都有分配器的模板参数。 template &lt;typename&gt; class container_t 不允许这样做,因此模板不匹配,因此调用了 void function(scalar_t value) 并且没有任何反应。

您需要做的是采用可变参数模板模板参数。使用

template <typename scalar_t, template <typename...> class container_t>
void function(const container_t<scalar_t> &container)
{
    for (const auto &value : container)
    {
        function(value);
        std::cout << ' ';
    }
}

你得到

012345F6F7 8 9 10 11F 12F 13F 14F 

Live Example

【讨论】:

  • 有趣的是,gccclang 在这段代码中的工作方式不同。 clang 正确吗?
  • @EdgarRokyan 这很有趣。 AFAIK,铿锵声在这里表现正确。我不确定为什么 gcc 接受它。
  • @EdgarRokyan 看起来 gcc 在 C++14 和 17 之间发生了一些变化。this 在 C++14 模式下编译失败,但在 C++17 模式下编译。现在我不确定 C++17 中是否发生了某些事情以允许它,或者它是否是 gcc 的 c++17 实现中的错误。
  • 我明白了...不幸的是,我不是模板专家,所以我不知道这种行为是否正确...
  • 这是在DR 150 中追溯更改的;旧行为是模板必须完全匹配,而新行为(追溯应用于 C++14)是您可以跳过带有默认参数的模板参数。\
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-04
  • 1970-01-01
  • 1970-01-01
  • 2021-11-12
相关资源
最近更新 更多