簡體   English   中英

使用另一個命名空間中的typedef進行ADL

[英]ADL with typedefs from another namespace

我有這樣的事情:

#include <iostream>
namespace N
{
   typedef std::pair<int, double> MyPair;
   std::ostream& operator << (std::ostream& o, MyPair const & mypair)
   {
      ///
   }
}

int main()
{
    N::MyPair pr;
    std::cout << pr;
}

這自然不起作用,因為ADL不會找到operator<<因為namespace NMyPair沒有關聯(遺憾的是)。 Afaik可能沒有添加到命名空間std,所以如果我選擇在std中定義operator <<有點非法。 那么......在這種情況下該怎么辦? 我不想明確限定operator << ,也不希望using namespace N編寫。 所以,問題是:

  1. 如何重構代碼?
  2. 為什么ADL不會關聯typedef的名稱空間? 嚴重的原因? 這會很好,例如在這種情況下。 謝謝
  1. 您可以在命名空間N中創建自己的類型,可能繼承自std :: pair。 你可以添加“using namespace N;” 在主要內部。 前者更有可能有用。

  2. 因為類型是在另一個命名空間中定義的,不能定義為兩個。

例:

namespace N { 
struct MyPair : std::pair<int, double> {
  MyPair(int first, double second) : std::pair<int, double>(first, second) {}
  // add defaults if desired: first=0, second=0.0
  // with defaults, you may want to make the ctor explicit or leave implicit

  // also, if desired and you don't use two defaults above:
  MyPair() : std::pair<int, double>(0, 0.0) {}

  // in 0x, you can "import" the base's ctors with a using declaration
};
}

如果用作std :: pair並不重要,可以刪除繼承並重命名成員。 在任何一種情況下,您當然可以添加其他方法,但如果保留繼承,則可以使用“重命名方法”:

int      & foo()       { return first; }
int const& foo() const { return first; }
double      & bar()       { return second; }
double const& bar() const { return second; }

我想不出typedef名稱不應該參與ADL的原因。 此外,它還定義了以下代碼實現:

#include <algorithm>
#include <vector>

namespace my {
class A {};
void for_each();
} // my

int main()
{
    std::vector<my::A> v;
    for_each(v.begin(), v.end(), [...]);
} 
  • 如果std::vector<T>::iterator是std命名空間中某個東西的typedef:將調用std::for_each
  • 如果std::vector<T>::iteratormy::A *的typedef:編譯器應該抱怨my::for_each不帶3個參數

您可以使用強大的typedef:

#include<boost/strong_typedef.hpp>    
#include<iostream>

namespace N
{
// typedef std::pair<int, double> MyPair;
   typedef std::pair<int, double> pair_int_double; 
   BOOST_STRONG_TYPEDEF(pair_int_double, MyPair);

   std::ostream& operator << (std::ostream& o, MyPair const & mypair)
   {
      return o;
   }
}

int main(){
    N::MyPair pr;
    std::cout << pr;
}

(為了避免宏中的額外逗號,仍然需要額外的typedef。)

您的選擇是:

  • 定義一個在其實現中使用std :: pair的新類型,而不是使用typedef
  • 為輸出功能使用不同的名稱
  • 在調用它時,明確限定所需的功能
  • (也許)專門化命名空間std中的函數(我不確定pair<int,double>算作UDT)

這一切都源於typedef的主要優點和缺點:typedef名稱只是同義詞。 無論您將其置於什么命名空間,typedef名稱都指向關聯類型,無論在何種類型的命名空間中定義。這與typedef不同,typedef是可轉換為關聯類型的新類型。 想象一下這種情況:

class C{};
typedef C id_t;
void f(C);
int f(id_t); // error: structurally equivalent to `int f(C);`

這是無效的,因為int和id_t不是不同的類型。 這擴展到ADL:

namespace A{
  class C{};
  void f(C);
  void g(C);
}

namespace B{
  typedef C id_t;
  int f(id_t); // structurally equivalent to `void f(C);`
}

B::id_t id; // completely equivalent to `A::C id;`
int n = f(id); // error: A::f doesn't return int

這里有一個問題:您是否認為以下內容無法編譯? 如果沒有,應如何解析名稱查找:

B::id_t id;
g(id);

我通過將相關符號拉入我想要使用它們的命名空間來解決這個問題:

#include <iostream>

namespace N
{
   typedef std::pair<int, double> MyPair;
   std::ostream& operator << (std::ostream& o, MyPair const & mypair)
   {
      ///
   }
}

using N::operator <<; // now it should compile

int main()
{
    N::MyPair pr;
    std::cout << pr;
}

如果您要輸出特定的數據類型,則可以始終定義自己的類,而不是使用std::pair

struct myPair
{
  int first;
  double second;
};

允許添加的模板功能專業化namespace::std但是因為沒有在使用的類型的MyPair是定義我不知道這樣的專業化是合法用戶。

namespace std {
     template<>
     ostream& operator<<(ostream& os, const MyPair& p) { }
}

暫無
暫無

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

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