2016-03-22 21 views
-1

不完全なテンプレートタイプを使用している問題があります。私はかなり長い間ソリューションを探してきましたが、私が見つけたすべての答えは、「ヘッダーを含める」、「前方に宣言する」、または「STLで行うことはできません」という行に沿っている傾向があります。私は間違ったことを探しているという気持ちがある、あるいはGoogleの最初の12ページが浸水していると感じている。エラー:不完全なテンプレートタイプ

私は間違いなく修正を探しているが、私は非常に説明、またはおそらく良いガイド。私はひどくテンプレートのOOPにかなり新しいです、何が間違って、それが間違っているのか、そしてなぜそれが何であるかを学びたいと思っています。

私はあなたに複数の500行のファイルを与えることなく、可能な限りAS MUCHコードを組み込もうとします。楕円は、この問題とは関係のないコード(または他の方向の繰り返しや大きなステンシルを削除した部分)を削除した場所です。また、SpatialOpsは空間操作に使用するライブラリです。私はここに投稿しているコードを削除すると、すべてがうまくリンクされ、すべてがCMakeなどでうまくコンパイルされます。エラーメッセージで開始 :ここ

/scratch/local/prism_large/dac/debugging/LBMS2/src/operators/Operators.cpp: In function ‘void LBMS::build_operators(const BundlePtr&)’: 
/scratch/local/prism_large/dac/debugging/LBMS2/src/operators/Operators.cpp:154:96: error: invalid use of incomplete type ‘SpatialOps::X2PosX {aka struct SpatialOps::OneSidedOpTypeBuilder<SpatialOps::Gradient, SpatialOps::OneSidedStencil2<SpatialOps::IndexTriplet<1, 0, 0> >, SpatialOps::SpatialField<LBMS::XVol, double> >}’ 
    opDB.register_new_operator<SpatialOps::X2PosX>(new SpatialOps::X2PosX(coefHalfDx2Plus )); 
                          ^
In file included from /scratch/local/prism_large/dac/debugging/LBMS2/src/operators/Operators.h:6:0, 
      from /scratch/local/prism_large/dac/debugging/LBMS2/src/operators/Operators.cpp:1: 
/scratch/local/prism_large/dac/debugging/spatialopsbuild/include/spatialops/structured/stencil/OneSidedOperatorTypes.h:115:10: error: declaration of ‘SpatialOps::X2PosX {aka struct SpatialOps::OneSidedOpTypeBuilder<SpatialOps::Gradient, SpatialOps::OneSidedStencil2<SpatialOps::IndexTriplet<1, 0, 0> >, SpatialOps::SpatialField<LBMS::XVol, double> >}’ 
    struct OneSidedOpTypeBuilder; 

はLBMSにおける問題のヘッダーファイル(我々のコードベース)です。 Operators.h =>

#ifndef LBMSOperators_h 
#define LBMSOperators_h 

#include <spatialops/structured/stencil/FVStaggeredBCOp.h> 
#include <spatialops/structured/stencil/FVStaggeredOperatorTypes.h> 
#include <spatialops/structured/stencil/OneSidedOperatorTypes.h> 

... 

#include <spatialops/structured/stencil/StencilBuilder.h> 
#include <spatialops/Nebo.h> 

/** 
* \file Operators.h 
* \brief Defines operators for use in LBMS. 
*/ 

namespace SpatialOps{ 
    class OperatorDatabase; // forward declaration 
} 

namespace SpatialOps{ 
... 

    typedef SpatialOps::OneSidedStencil2< SpatialOps::UnitTriplet<SpatialOps::XDIR>::type   > X2PlusT; 
    typedef SpatialOps::OneSidedOpTypeBuilder<SpatialOps::Gradient, X2PlusT, LBMS::XVolField> X2PosX; 
... 

} // namespace SpatialOps 
#endif // LBMSOperators_h 

および対応するcppファイル。 Operators.cpp =>

#include "Operators.h" 

... 

//--- SpatialOps Headers ---// 
#include <spatialops/OperatorDatabase.h> 
#include <spatialops/structured/stencil/StencilBuilder.h> 
#include <spatialops/Nebo.h> 

using namespace SpatialOps; 
... 

namespace LBMS{ 
... 

    void 
    build_operators(const BundlePtr& bundle) 
    { 
    SpatialOps::OperatorDatabase& opDB = bundle->operator_database(); 

    const double dx = bundle->spacing(XDIR); 
    NeboStencilCoefCollection<2> coefHalfDx2Plus = build_two_point_coef_collection(-1.0/dx, 1.0/dx); 
... 

    opDB.register_new_operator<SpatialOps::X2PosX>(new SpatialOps::X2PosX(coefHalfDx2Plus )); 
... 

    } 
} // namespace LBMS 

これは私が利用しようとしている演算子を含むライブラリのヘッダです(LBMSでも)。 OneSidedOperatorTypes.h =>

#ifndef SpatialOps_structured_OneSidedOpTypes_h 
#define SpatialOps_structured_OneSidedOpTypes_h 

#include <spatialops/SpatialOpsDefs.h> 
#include <spatialops/Nebo.h> 

namespace SpatialOps{ 

    template<typename Op, typename StencilT, typename FieldT, typename Offset=IndexTriplet<0,0,0> > 
    class OneSidedOpTypeBuilder; // forward declaration 
} 
/** 
    * \struct OneSidedStencil2 
    * \brief Support for one-sided stencils. 
    * \tparam OpDir the unit vector (a IndexTriplet) that indicates the direction of offset for the stencil. 
    * \tparam Offset (optional) the offset for the stencil. <0,0,0> (default) results in a 
    *   one-sided stencil that computes into the first stencil point. 
    *   <1,0,0> would offset the stencil so that it effectively computes 
    *   into the <-1,0,0> point. 
    * 
    * \par Example: 
    * This code describes a 2-point stencil oriented in the (+x) direction. 
    * \code{.cpp} 
    * OneSidedStencil2< IndexTriplet<1,0,0> > 
    * \endcode 
    * It would look something like this: 
    * \verbatim 
      1 2 3 
    Read : o o o 
    Write: o 
    \endverbatim 
    * 
    * \par Example: 
    * This code describes a 2-point stencil oriented in the (-x) direction that 
    * is offset in the (-x) direction. 
    * \code{.cpp} 
    * OneSidedStencil2< IndexTriplet<-1,0,0>, IndexTriplet<-1,0,0> > 
    * \endcode 
    * It would look something like this: 
    * \verbatim 
      n-2 n-1 n 
    Read : o o 
    Write:   o 
    \endverbatim 
    */ 
    template<typename OpDir, typename Offset=IndexTriplet<0,0,0> > 
    struct OneSidedStencil2{ 
    typedef OpDir DirT; ///< The orientation of the stencil (IndexTriplet) 
    typedef typename Add<Offset,OpDir>::result Point2; 
    typedef NEBO_FIRST_POINT(Offset)::NEBO_ADD_POINT(Point2) StPtCollection; 
    }; 

... 

    /** 
    * \struct OneSidedOpTypeBuilder 
    * \ingroup optypes 
    * \brief Builds OneSidedDiv operator type from field type. 
    * 
    * \tparam Op the basic operator type (e.g., Gradient, Interpolant) 
    * \tparam StencilT the stencil structure (e.g., OneSidedStencil3<IndexTriplet<0,-1,0>) 
    * \tparam FieldT the field that the operator applies to (e.g., SVolField) 
    * \tparam Offset the offset for the stencil. <0,0,0> (default) results in a 
    *   one-sided stencil that computes into the first stencil point. 
    *   <1,0,0> would offset the stencil so that it effectively computes 
    *   into the <-1,0,0> point. 
    * 
    * \par Example Usage 
    * The following obtains the full type for a two-point, one-sided stencil 
    * shifted in the (-z) direction: 
    * \code 
    * typedef UnitTriplet<ZDIR>::type::Negate ZMinus; 
    * typedef OneSidedOpTypeBuilder<Gradient,OneSidedStencil2<ZMinus>,SVolField>::type OneSidedDiv2Z; 
    * \endcode 
    * 
    * Note that we only provide fully specialized versions of this template 
    * so that unsupported operator types cannot be inadvertently formed. 
    */ 
    template<typename Op, typename StencilT, typename FieldT, typename Offset=IndexTriplet<0,0,0> > 
    struct OneSidedOpTypeBuilder; 

#define BUILD_ONE_SIDED_OP_ACROSS_DIRS(Op, I1, I2, I3, StencilT, FieldT)         \ 
    template<> struct OneSidedOpTypeBuilder<Op,StencilT<IndexTriplet<I1,I2,I3> >,FieldT>{      \ 
typedef NeboStencilBuilder<Op,StencilT<IndexTriplet<I1,I2,I3> >::StPtCollection, FieldT, FieldT> type; \ 
    }; 

#define ONE_SIDED_OP_BUILDERS(Op, I1, I2, I3, FieldT)      \ 
    BUILD_ONE_SIDED_OP_ACROSS_DIRS(Op, I1, I2, I3, OneSidedStencil2, FieldT) \ 

... 

#define BUILD_ONE_SIDED_STENCILS(FieldT)    \ 
    ONE_SIDED_OP_BUILDERS(Gradient, 1, 0, 0, FieldT) \ 
    ONE_SIDED_OP_BUILDERS(Gradient, -1, 0, 0, FieldT) \ 
    ONE_SIDED_OP_BUILDERS(Gradient, 0, 1, 0, FieldT) \ 
    ONE_SIDED_OP_BUILDERS(Gradient, 0,-1, 0, FieldT) \ 
    ONE_SIDED_OP_BUILDERS(Gradient, 0, 0, 1, FieldT) \ 
    ONE_SIDED_OP_BUILDERS(Gradient, 0, 0,-1, FieldT) 

... 

BUILD_ONE_SIDED_STENCILS( XVolField) 

... 

} // namespace SpatialOps 

#endif // SpatialOps_structured_OneSidedOpTypes_h 

私は楽しみな

namespace SpatialOps{ 
    template<typename Op, typename StencilT, typename FieldT> 
    struct OneSidedOpTypeBuilder; // forward declaration 
} 

として、Operators.hに宣言するなら、私は次のエラー・メッセージを参照してください。 /スクラッチ/ローカル/ prism_large/DAC /デバッグ/LBMS2/src/operators/Operators.h:28:9:エラー: 'class Offset'のデフォルト引数の再定義 class OneSidedOpTypeBuilder; //前方宣言

または私は前方に、デフォルトのテンプレート引数を含む場合Operators.hに宣言し、

私は次のエラーを取得:

[ 30%] Building CXX object src/CMakeFiles/lbms.dir/lbms/ProblemSolver.cpp.o 
In file included from /scratch/local/prism_large/dac/debugging/LBMS2/src/transport/TransportEquationBase.h:40:0, 
      from /scratch/local/prism_large/dac/debugging/LBMS2/src/lbms/ProblemSolver.h:38, 
      from /scratch/local/prism_large/dac/debugging/LBMS2/src/lbms/ProblemSolver.cpp:29: 
/scratch/local/prism_large/dac/debugging/LBMS2/src/operators/Operators.h:28:10: error: redefinition of default argument for ‘class Offset’ 
    struct OneSidedOpTypeBuilder; // forward declaration 
     ^
In file included from /scratch/local/prism_large/dac/debugging/nscbcbuild/include/nscbc/NSCBCToolsAndDefs.h:18:0, 
      from /scratch/local/prism_large/dac/debugging/LBMS2/src/lbms/BCOptions.h:43, 
      from /scratch/local/prism_large/dac/debugging/LBMS2/src/lbms/ProblemSolver.h:30, 
      from /scratch/local/prism_large/dac/debugging/LBMS2/src/lbms/ProblemSolver.cpp:29: 
/scratch/local/prism_large/dac/debugging/spatialopsbuild/include/spatialops/structured/stencil/OneSidedOperatorTypes.h:114:61: note: original definition appeared here 
    template<typename Op, typename StencilT, typename FieldT, typename Offset=IndexTriplet<0,0,0> > 

または私はデフォルトが含まれていない場合をテンプレートの議論では、私は最初に次のように始めています:

/scratch/local/prism_large/dac/debugging/LBMS2/src/operators/Operators.cpp: In function ‘void LBMS::build_operators(const BundlePtr&)’: 
/scratch/local/prism_large/dac/debugging/LBMS2/src/operators/Operators.cpp:154:96: error: invalid use of incomplete type ‘SpatialOps::X2PosX {aka struct SpatialOps::OneSidedOpTypeBuilder<SpatialOps::Gradient, SpatialOps::OneSidedStencil2<SpatialOps::IndexTriplet<1, 0, 0> >, SpatialOps::SpatialField<LBMS::XVol, double> >}’ 
    opDB.register_new_operator<SpatialOps::X2PosX>(new SpatialOps::X2PosX(coefHalfDx2Plus )); 
                           ^
In file included from /scratch/local/prism_large/dac/debugging/LBMS2/src/operators/Operators.h:6:0, 
      from /scratch/local/prism_large/dac/debugging/LBMS2/src/operators/Operators.cpp:1: 
/scratch/local/prism_large/dac/debugging/spatialopsbuild/include/spatialops/structured/stencil/OneSidedOperatorTypes.h:115:10: error: declaration of ‘SpatialOps::X2PosX {aka struct SpatialOps::OneSidedOpTypeBuilder<SpatialOps::Gradient, SpatialOps::OneSidedStencil2<SpatialOps::IndexTriplet<1, 0, 0> >, SpatialOps::SpatialField<LBMS::XVol, double> >}’ 
    struct OneSidedOpTypeBuilder; 
     ^

私に含めるべきことが他にある場合は教えてください。一方では、私はすべてを含めることの重要性をよく理解していますが、他方では、これらの図書館の一部はかなり大きくなっています。

ありがとうございました!

答えて

0

OneSidedOpTypeBuilderクラスのウェブで検索したところ、定義されているヘッダーファイルが見つかりました。そのファイルを見ると、フォワードリファレンスの下に、テンプレートの特殊化を作成するためのプリプロセッサマクロがあることがわかります。

#define ONE_SIDED_OP_BUILDER(OP, STYLE, FIELD)      \ 
    template<>               \ 
    struct OneSidedOpTypeBuilder<OP,FIELD>{        \ 
     typedef NeboStencilBuilder<OP,          \ 
            STYLE<OP,FIELD>::StPtCollection,   \ 
            FIELD,         \ 
            FIELD>         \ 
       type;              \ 
    }; 

私はあなたが間違ってOneSidedOpTypeBuilderを使用していると考えていると、あなたのX2PosXタイプのtypedef前

ONE_SIDED_OP_BUILDER(SpatialOps::Gradient, X2PlusT, LBMS::XVolField); 

ような何かをする必要があります。