10

私の完全なコードは長すぎますが、ここに私の問題の本質を反映するスニペットがあります:

class BPCFGParser {
  public:

  ...
  ...

  class Edge {
    ...
    ...
  };


  class ActiveEquivClass {
    ...
    ...
  };

  class PassiveEquivClass {
    ...
    ...
  };

  struct EqActiveEquivClass {
    ...
    ...
  };

  struct EqPassiveEquivClass {
    ...
    ...
  };



  unordered_map<ActiveEquivClass, Edge *, hash<ActiveEquivClass>, EqActiveEquivClass> discovered_active_edges;
  unordered_map<PassiveEquivClass, Edge *, hash<PassiveEquivClass>, EqPassiveEquivClass> discovered_passive_edges;

};

namespace std {


template <>
class hash<BPCFGParser::ActiveEquivClass>
{

    public:
        size_t operator()(const BPCFGParser::ActiveEquivClass & aec) const {

        }
};

template <>
class hash<BPCFGParser::PassiveEquivClass>
{

    public:
        size_t operator()(const BPCFGParser::PassiveEquivClass & pec) const {

        }
};

}

このコードをコンパイルすると、次のエラーが発生します。

In file included from BPCFGParser.cpp:3,
                 from experiments.cpp:2:
BPCFGParser.h:408: error: specialization of ‘std::hash<BPCFGParser::ActiveEquivClass>’     after instantiation
BPCFGParser.h:408: error: redefinition of ‘class                 std::hash<BPCFGParser::ActiveEquivClass>’
/usr/include/c++/4.3/tr1_impl/functional_hash.h:44: error: previous definition of     ‘class std::hash<BPCFGParser::ActiveEquivClass>’
BPCFGParser.h:445: error: specialization of     ‘std::hash<BPCFGParser::PassiveEquivClass>’ after instantiation
BPCFGParser.h:445: error: redefinition of ‘class std::hash<BPCFGParser::PassiveEquivClass>’
/usr/include/c++/4.3/tr1_impl/functional_hash.h:44: error: previous definition of     ‘class std::hash<BPCFGParser::PassiveEquivClass>’

ここで、これらのクラス用に std::hash を特殊化する必要があります (標準の std::hash 定義にはユーザー定義型が含まれていないため)。これらのテンプレートの特殊化を class の定義の前に移動するとBPCFGParser、さまざまなことを試みたときにさまざまなエラーが発生し、どこか ( http://www.parashift.com/c++-faq-lite/misc-technical-issues .html ) 私はそれを読みました:

クラスをテンプレート パラメーターとして使用する場合は常に、そのクラスの宣言を完全にする必要があり、単純に前方宣言するのではありません。

だから私は立ち往生しています。BPCFGParser定義後にテンプレートを特殊化することはできません。また、定義前にテンプレートを特殊化することもできませんBPCFGParser。どうすればこれを機能させることができますか?


特殊化を BPCFGParser 内の内部クラスに移動する必要があります。そうすることで、両方の要件が満たされます。

答えてくれてどうもありがとう:)

hashclass は namespace 内で定義されますstdhash名前空間以外のスコープでテンプレートを特殊化することはできません。以下でも:

template <>
  class std::hash<ActiveEquivClass> {
...

動作しませんでした。ただし、特殊化を で囲むとnamespace std {}、次の奇妙なエラーが発生します。

In file included from BPCFGParser.cpp:3,
                 from experiments.cpp:2:
BPCFGParser.h:225: error: expected unqualified-id before ‘namespace’
experiments.cpp:7: error: expected `}' at end of input
BPCFGParser.h:222: error: expected unqualified-id at end of input

velocityreviewsで与えられた回答で、誰かが名前空間をクラス内で定義できないと主張しています。だから私はまだ立ち往生しています。

4

6 に答える 6

7

特殊化を BPCFGParser 内の内部クラスに移動する必要があります。そうすることで両方の要件を満たします

  1. 専門化は完全な定義の後にあるActiveEquivClass
  2. スペシャリゼーションを使用する前に

例:

class BPCFGParser {

  class ActiveEquivClass {
    ...
  };

  template <>
  class hash<ActiveEquivClass> {
     public:
        size_t operator()(const BPCFGParser::ActiveEquivClass & aec) const {
        }
  };
  ...
  unordered_map<ActiveEquivClass, Edge *, hash<ActiveEquivClass>, EqActiveEquivClass> discovered_active_edges;

};
于 2009-12-12T20:02:10.473 に答える
2

この質問はかなり古いことは知っていますが、同じ問題に遭遇したばかりで、調査結果を報告すると思いました。

エラーメッセージ:

In file included from BPCFGParser.cpp:3,
             from experiments.cpp:2:
BPCFGParser.h:408: error: specialization of ‘std::hash<BPCFGParser::ActiveEquivClass>’     after instantiation
BPCFGParser.h:408: error: redefinition of ‘class                 std::hash<BPCFGParser::ActiveEquivClass>’
/usr/include/c++/4.3/tr1_impl/functional_hash.h:44: error: previous definition of     ‘class std::hash<BPCFGParser::ActiveEquivClass>’
BPCFGParser.h:445: error: specialization of     ‘std::hash<BPCFGParser::PassiveEquivClass>’ after instantiation
BPCFGParser.h:445: error: redefinition of ‘class std::hash<BPCFGParser::PassiveEquivClass>’
/usr/include/c++/4.3/tr1_impl/functional_hash.h:44: error: previous definition of     ‘class std::hash<BPCFGParser::PassiveEquivClass>’

std::hash のジェネリック テンプレートまたは既存の特殊化のいずれかが既に使用されているため、std::hash を特殊化できないと言っています。それが定義されたポイントと、それを特化しようとしているポイント。

このドキュメントの「詳細」セクションに、これを説明するテキストがあります。

特殊化は、暗黙的なインスタンス化を引き起こす最初の使用の前に宣言する必要があります

私の場合、問題は専門化コードにあるのではなく、その位置にありました。std::hash を使用すると、それ以上特殊化することはできません。

<unordered_map> をインクルードした直後に特殊化コードを移動すると、正常に機能することがわかりました。

特殊化の宣言を実装から分離するという Puppy の提案により、宣言を <unordered_map> のインクルードに非常に近づけることができます。実装は、都合の良い場所ならどこでも後で行うことができます (ケースで BPCFGParser が完全に定義された後)。

于 2016-03-04T17:05:31.740 に答える
1

Hash<> テンプレート特殊化コードを BPCFGParser クラス宣言の前に移動してみてください。このエラーは、/usr/include/c++/4.3/tr1_impl/functional_hash.h で定義された std::hash に基づいてハッシュが展開されていることを意味します。したがって、インスタンス化の前に専門化は使用されません。理想的には、テンプレートを展開する前に、特殊化コードをコンパイラで使用できるようにする必要があります。

于 2010-04-13T07:59:52.590 に答える
0

私はまったく同じ問題を抱えており、最終的に回避策のユーザー定義のハッシュ ファンクター ソリューションを考え出しました。以下を参照してください。

class Outer
{
    // TC++PL, 4e, 19.4.1 : A friend must be previously declared in an enclosing scope or
    // defined in the non-class scope immediately enclosing the class that is declaring it to be a friend. 
    struct Hash_inner;

    class Inner
    {
        int i;
        friend struct Hash_inner;
    };

    struct Hash_inner
    {
        size_t operator()(const Inner& in) const
        { return std::hash<int>()(in.i); }
    };

    std::unordered_map<Inner, int, Hash_inner> um;
};

そして、 std::hash 特殊化アプローチがあるかどうかまだ疑問に思っています。誰でもそれを理解できますか?

于 2013-09-18T13:27:27.530 に答える
0

クラスをテンプレート パラメーターとして使用する場合は常に、そのクラスの宣言を完全にする必要があり、単純に前方宣言するのではありません。

これは実際には正しくありません。テンプレート パラメーターが完全な型でなければならない場合の制限は、通常、テンプレートの内容に依存します。ただし、テンプレートに不完全な型で違法なコードが含まれていない限り、不完全な型でテンプレートをインスタンス化することは違法ではありません。

問題にアプローチする唯一の方法は、クラスの前に特殊化を定義することですが、クラスのoperator() に実際のメンバー関数を定義することです。あれは、

template <>
class std::hash<BPCFGParser::ActiveEquivClass>
{
public:
    size_t operator()(const BPCFGParser::ActiveEquivClass & aec) const;
};

// definition of BPCFGParser

template<> std::size_t std::hash<BPCFGParser::ActiveEquivClass>::operator()(const BPCFGParser::ActiveEquivClass & aec) const {
}

これは、ネストされたクラスを前方宣言できないため、ネストされたクラスがないことも意味します。

于 2012-05-09T00:43:39.450 に答える