【问题标题】:Declare template function to accept any container but only one contained type声明模板函数以接受任何容器,但只有一个包含的类型
【发布时间】:2017-09-29 08:46:04
【问题描述】:

我想声明一个接受不同 STL 容器的函数,但它们必须包含特定类的对象(例如,它应该接受 std::vector<double>std::deque<double>,但不接受 std::vector<std::string>)。

我已经找到了模板化容器和包含类型的答案,但我尝试调整它们以修复包含类型的尝试没有成功。

【问题讨论】:

  • 您尝试过什么?你的尝试给你带来了什么问题?
  • ^那个。提示:value_type
  • @PasserBy 你说的是 Henri Menke 的第二种方法吗?我曾想过静态断言,但认为可能有更优雅的解决方案。

标签: c++ templates stl


【解决方案1】:

您可以使用模板模板参数来做到这一点(没有错字)。模板函数的第一个模板参数是另一个具有可变数量模板参数的模板。第二个模板参数是可变参数模板参数。然后在签名中将第一个模板参数固定为您想要的类型(例如double)并让编译器推断出其余的。

#include <deque>
#include <iostream>
#include <string>
#include <vector>

template < template < class ... > class Container, class ... Args >
void any_container(Container<double, Args...>)
{
    // print what was deduced
    std::cout << __PRETTY_FUNCTION__ << '\n';
}

int main()
{
    std::vector<double> vd;
    any_container(vd);

    std::deque<double> dd;
    any_container(dd);

    std::vector<std::string> vs;
    any_container(vs); // BOOM!
}

@PasserBy 已经暗示了一个不同的解决方案in this comment。除了替换失败,您还可以将容器作为模板参数,并在static_assert 中查询其value_type。这样做的好处是您可以放置​​自定义错误消息。

#include <deque>
#include <iostream>
#include <string>
#include <type_traits>
#include <vector>

template <typename Container> void any_container(Container)
{
    static_assert(std::is_same<typename Container::value_type, double>::value,
                  "BOOM!");
    // print what was deduced
    std::cout << __PRETTY_FUNCTION__ << '\n';
}

int main()
{
    std::vector<double> vd;
    any_container(vd);

    std::deque<double> dd;
    any_container(dd);

    std::vector<std::string> vs;
    any_container(vs); // BOOM!
}

【讨论】:

  • __PRETTY_FUNCTION__ 不是标准的。它在 GCC 和 Clang 中可用,并且不是预处理器的一部分(与例如 __LINE__ 形成对比)。
  • 所以如果我理解正确的话,这有点小题大做,对吧?我声明我将使用可变数量的模板参数,然后每次结果都是 0,但这允许我修复第一个参数,否则这是不可能的。是这样吗?
  • @user2891462 请参阅下面的替代解决方案。
  • @user2891462 在上面的例子中,参数的可变数量永远不会为零。 std::vector 有第二个模板参数,即分配器,默认为标准分配器。
  • 我明白了,谢谢你的解释。我更喜欢第一种方法,因为函数声明中的类型更清晰:)
猜你喜欢
  • 2019-11-09
  • 1970-01-01
  • 2016-01-01
  • 2011-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-10
  • 2019-04-30
相关资源
最近更新 更多