错误:模板类型不完整
Error: Incomplete templated type
我使用不完整的模板类型时遇到问题。我已经搜索了很长一段时间的解决方案,但我找到的每一个答案都倾向于"包括标题"、"向前声明"或"你不能用STL这样做"。我有一种感觉,我在找错误的东西,或者谷歌的前十几页都被淹没了
虽然我肯定在寻找解决方案,但我非常感谢你的解释,或者一个好指南的链接。我对高度模板化的OOP还很陌生,我很想了解什么是错误的,它是如何错误的,以及为什么。
所以我将尝试包含尽可能多的代码,而不给你们多个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=>
#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文件。操作员.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
如果我在Operators.h中转发申报,如
namespace SpatialOps{
template<typename Op, typename StencilT, typename FieldT>
struct OneSidedOpTypeBuilder; // forward declaration
}
然后我看到以下错误消息:/scratch/local/prism_larg/dac/debug/LBMS2/src/operators/operators.h:28:9:error:重新定义"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;
^
如果还有什么需要我介绍的,请告诉我。一方面,我非常理解包含所有内容的重要性,但另一方面,这些图书馆中的一些相当大。
谢谢大家!
在web上搜索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之前。
- 类没有命名C++代码中的类型错误
- 不完整类型错误(E0409、E0070、E0515)
- 使用具有结构不完整类型错误的模板
- 不命名构造函数和析构函数上的类型错误
- 返回派生类型时出现协变类型错误
- 为什么此构造函数没有给出不完整的类型错误?
- 定义模板化结构的特征时出现不完整的类型错误
- 使用重载构造函数时出现不完整的类型错误
- 为什么我得到表达式必须有类类型错误?
- 输出 [left]=input[i] 行中的 c++ 代码中存在无效的类型错误
- 枚举成员不是类型错误
- 如何修复"ctypes"。参数错误:参数 2:<键入"异常.类型错误">:RaspberryPi 中的错误类型"错误
- 外部 "C" Visual Studio 2015 中的显式类型错误,DLL 测试代码
- 非默认析构函数会导致不完整的类型错误
- 为什么按引用传入会导致绑定引用类型错误
- Objective-C C++ 包装器 类型错误的不完整定义
- 输入类型错误
- 当构造函数的参数类型错误时引发异常
- 命名空间中的'bad_cast' 'std' 未命名类型错误
- C UNWORKOWN类型错误