容器类型的模板专业化

问题描述 投票:0回答:2

当类型是容器与非容器类型时,我希望对函数有单独的专业化。例如:

template <typename T>
void print(const T& t) {
  cout << "non-container: " << t;
}

template <>
void print(const ContainerType& container) {
  cout << "container: ";
  for (const auto& t : container) {
    cout << t;
  }
}

然后我可以使用这些功能,例如:

print(3); // Prints non-container: 3
print(vector{1, 1, 2}); // Prints container: 1 1 3
print(set{1, 1, 2}); // Prints container: 1 2

我不知道如何指定 print 的专业化,以便它会被

vector
set
调用,但不会被 int 调用。我不想为每个容器类型创建单独的专业化,我想要为任何可迭代类型创建一个专业化。

c++ templates
2个回答
4
投票

快速版本可能是

struct low_priority_tag {};
struct high_priority_tag : low_priority_tag {};

template <typename T>
std::false_type is_container_impl(const T& t, low_priority_tag);

template <typename T>
auto is_container_impl(const T& container, high_priority_tag)
-> decltype(std::begin(container), std::end(container), std::true_type{});

template <typename T>
using is_container = decltype(is_container_impl(std::declval<T>(), high_priority_tag{}));

template <typename T>
void print(const T& t) {
    if constexpr (is_container<T>::value) {
        std::cout << "container: {";
        const char* sep = "";
        for (const auto& e : t) {
            std::cout << sep;
            print(e);
            sep = ", ";
        }
        std::cout << "}";
    } else {
        std::cout << t;   
    }
}

演示

在 C++20 中,使用

concept
:

template <typename T>
concept Container = requires(T t)
{
    std::begin(t);
    std::end(t);
};

template <typename T>
void print(const T& t) {
    std::cout << t;   
}

template <Container C>
void print(const C& c) {
    std::cout << "container: {";
    const char* sep = "";
    for (const auto& e : c) {
        std::cout << sep;
        print(e);
        sep = ", ";
    }
    std::cout << "}";
}

演示


0
投票

自 C++20 起,可以使用概念

std::ranges::input_range
来约束第二个函数重载。它本质上是对范围的细化,
std::ranges::begin()
函数返回
std::input_iterator
的模型。

示例:

template <typename T>
void print(const T& t)
{ std::cout << "non-container: " << t; }

template <std::ranges::input_range T>
void print(const T& x) {
  std::cout << "container: ";
  for (const auto& t : x)
    std::cout << t;
}
© www.soinside.com 2019 - 2024. All rights reserved.