我遇到使用不完全模板类型的问题。我已经搜索了很长一段时间才找到解决方案,但我找到的每个答案都倾向于按照#34;包括标题," "转发声明,"或者"你不能用STL做到这一点。"我有一种感觉,我正在寻找错误的东西,或者前十几页谷歌被淹没
虽然我肯定在寻找解决方案,但我非常感谢您的解释,或者可能是指向良好指南的链接。对于模仿严重的OOP我很新,并且很想知道错误是什么,错误是什么以及原因。
因此,我将尝试尽可能包含AS MUCH代码,而不会向您提供多个500行文件。省略号是我删除与此问题无关的代码(或者我删除了其他方向迭代和更大的模板的地方)。此外,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 =&gt;
#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 =&gt;
#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 =&gt;
#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
如果我在Operators.h中转发声明,例如
namespace SpatialOps{
template<typename Op, typename StencilT, typename FieldT>
struct OneSidedOpTypeBuilder; // forward declaration
}
然后我看到以下错误消息: /scratch/local/prism_large/dac/debugging/LBMS2/src/operators/Operators.h:28:9:错误:重新定义'class Offset'的默认参数 class OneSidedOpTypeBuilder; //前向声明
或者,如果我在Operators.h中的forward declare中包含默认模板参数,
我收到以下错误:
[ 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 :(得分: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
并需要执行类似
ONE_SIDED_OP_BUILDER(SpatialOps::Gradient, X2PlusT, LBMS::XVolField);
在X2PosX
类型的typedef之前。