簡體   English   中英

std :: vector和std :: list的重載運算符

[英]Overload operator for both std::vector and std::list

我想使用以下代碼為std::liststd::vector重載operator<< 但這兩個功能幾乎相同。 有沒有辦法將它們組合起來, 創建一個更通用的重載?

#include <iterator>
#include <iostream>
#include <vector>
#include <list>

template <typename T>
std::ostream &operator<<(std::ostream &out, const std::vector<T> &v)
{
  if (!v.empty())
    std::copy(v.begin(), v.end(), std::ostream_iterator<T>(out, ", "));
  return out;
}

template <typename T>
std::ostream &operator<<(std::ostream &out, const std::list<T> &v)
{
  if (!v.empty())
    std::copy(v.begin(), v.end(), std::ostream_iterator<T>(out, ", "));
  return out;
}

int main()
{
  std::cout << std::vector<int>({1, 2, 3, 4}) << std::endl;
  std::cout << std::list<int>({1, 2, 3, 4}) << std::endl;
  return 0;
}

您可以將模板與模板參數一起使用如以下示例所示:

template <typename T, typename A, template <typename X, typename Y> class C> 
std::ostream &operator<<(std::ostream &os, const C<T,A> &container)
{
  if(!container.empty())
    std::copy(container.begin(), container.end(), std::ostream_iterator<T>(os, " "));
  return os;
}

int main() {
    list<int> l{1,2,3,4,5}; 
    vector<string> v{"one","two","three"};
    cout<<l<<endl<<v; 
    return 0;
}

在線演示

順便說一句,你可以在這個SO問題中找到使用模板模板的其他例子。

但是你必須小心這種結構:

  • 它僅適用於使用兩個模板參數定義的容器(對於列表和向量是好的;但對於集合或映射則不行)。
  • 它可能與使用兩個參數的其他模板類型沖突,因為沒有提取器的特化。

備注: 如果您尋找通用解決方案,最好考慮創建一個使用迭代器作為參數的適配器模板,然后為此適配器編寫通用提取器。

輸入C ++ 20以及可能包含的概念范圍 ,您的問題的解決方案可以大大簡化。

概念基本上是具有約束的模板參數,例如

// Taken from https://en.cppreference.com/w/cpp/experimental/constraints
template <typename T>
concept bool Integral = std::is_integral<T>::value;

template <Integral T> // Using concept Integral.
void foo(T i) { /* ... */ } // 'i' has to be integral, or compile time error.

現在, Range (簡化)的概念符合接口(偽代碼):

Range {
    begin()
    end()
}

使用它,可以編寫如下內容:

template <Range T>
std::ostream& operator<<(std::ostream& out, T&& rng) {
    std::copy(std::forward<T>(rng), std::make_ostream_joiner(out, ", "));
    return out;
}

它適用於任何有begin()end() ,例如

std::cout << std::vector{1, 2, 3, 4, 5} << std::endl; // Ok
std::cout << std::list{1, 2, 3, 4, 5} << std::endl; // Ok

另外,請注意我使用std::make_ostream_joiner而不是std::ostream_iterator 它使用了一個新的C ++ 20迭代器std::ostream_joiner ,它在跳過額外尾隨分隔符的每兩個對象之間寫入分隔符,即你將獲得"1, 2, 3, 4, 5"而不是"1, 2, 3, 4, 5, "

讓我們希望所有這些功能都成為C ++ 20 :)

注意:給出的所有示例都是假設的C ++ 20代碼,目前不使用我所知的任何發布 - 構建編譯器進行編譯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM