18

私はこのようなものを持っています:

#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<<ため、これは当然機能しません。私の知る限り、名前空間 std に追加できない場合があるため、std で定義することを選択した場合、それはちょっと違法になります。では...そのような状況ではどうすればよいですか?を明示的に修飾したくはありませんし、書きたくもありません。したがって、質問は次のとおりです。namespace NMyPairoperator <<operator <<using namespace N

  1. コードをリファクタリングするには?
  2. ADL が typedef の名前空間を関連付けないのはなぜですか? 深刻な理由?たとえば、この場合はいいでしょう。ありがとう
4

7 に答える 7

4

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>::iteratorstd 名前空間にある何かの typedef の場合:std::for_eachが呼び出されます
  • std::vector<T>::iteratorが の typedef の場合:コンパイラは3 つの引数を取らないmy::A *と文句を言う必要がありますmy::for_each
于 2010-11-11T15:39:07.147 に答える
4
  1. おそらく std::pair から継承して、名前空間 N に独自の型を作成できます。「using namespace N;」を追加できます。内部メイン。前者の方が有用である可能性が高くなります。

  2. 型が別の名前空間で定義されており、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; }
于 2010-11-11T14:41:28.660 に答える
2

関連するシンボルを使用したい名前空間にプルすることで、この問題を解決します。

#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;
}
于 2014-07-12T13:53:08.147 に答える
2

オプションは次のとおりです。

  • typedef を使用する代わりに、その実装で std::pair を使用する新しい型を定義します
  • 出力関数に別の名前を使用する
  • 呼び出すときに必要な関数を明示的に修飾する
  • (多分) 名前空間 std で関数を特殊化します ( pair<int,double>UDT としてカウントされるかどうかはわかりません)

これはすべて、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);
于 2010-11-11T16:31:58.107 に答える
2

強力な 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 が必要です。)

于 2015-01-14T10:13:21.880 に答える
1

テンプレート関数の特殊化を追加することnamespace::std許可されていますが、で使用されるタイプはいずれもMyPairユーザー定義ではないため、そのような特殊化が合法かどうかはわかりません。

namespace std {
     template<>
     ostream& operator<<(ostream& os, const MyPair& p) { }
}
于 2010-11-11T15:45:34.350 に答える
1

出力したい特定のデータ型がある場合は、 を使用するのではなく、いつでも独自のクラスを定義できますstd::pair

struct myPair
{
  int first;
  double second;
};
于 2010-11-11T14:42:06.870 に答える