嵌套名称说明符中使用的不完整类型,为什么?
incomplete type used in nested name specifier, Why?
以下代码是固定长度算术类型的一部分,我尽可能地将其简化为只包含问题。
namespace MathX
{
typedef signed int int32;
typedef unsigned int uint32;
typedef signed long long int64;
typedef unsigned long long uint64;
typedef uint32 mathx_ucomp;
typedef int32 mathx_scomp;
typedef uint64 mathx_udcomp;
typedef int64 mathx_sdcomp;
template<typename t>
struct sizeof_ex
{
static const uint32 value = sizeof(t) * 8;
};
template<uint64 val>
struct is_power_of_2
{
static const bool value = !(val & (val - 1u));
};
enum type_classes { tc_native, tc_custom };
enum type_ids { ti_basic_int, ti_basic_float, ti_int_t, ti_uint_t, ti_float_t };
template <typename t>
struct basic_info
{
static const bool is_signed = (t(-1) == -1);
static const bool is_integer = (t(3.14) != 3.14);
static const uint32 num_of_bits = sizeof_ex<t>::value;
static const uint32 comp_bits = num_of_bits;
static const type_classes type_class = tc_native;
static const type_ids type_id = is_integer? ti_basic_int: ti_basic_float;
};
template<typename t>
struct global_int
{
static const t zero;
static const t one;
static const t mone;
static const t minval;
static const t maxval;
static const uint32 full_t = is_power_of_2<basic_info<t>::num_of_bits>::value? basic_info<t>::num_of_bits: 0u;
static const uint32 used_t = full_t - int32(basic_info<t>::type_id == ti_int_t);
static const bool sign_t = (full_t != used_t);
static const uint32 half_t = full_t >> 1u;
static const uint32 comp_b = is_power_of_2<basic_info<t>::comp_bits>::value? basic_info<t>::comp_bits: 0;
static const uint32 comp_d = comp_b << 1u;
static const uint32 comp_c = full_t / comp_b;
};
template<typename t> const t global_int<t>::zero = t(0u);
template<typename t> const t global_int<t>::one = t(1u);
template<typename t> const t global_int<t>::mone = t(-1);
template<typename t> const t global_int<t>::minval = t(global_int<t>::sign_t? (typename t::ucomp)1 << (global_int<t>::comp_b - 1): 0, 0);
template<typename t> const t global_int<t>::maxval = t(global_int<t>::sign_t? (typename t::ucomp)~0 >> 1: (typename t::ucomp)~0, (typename t::ucomp)~0);
template <uint32 bit_count, typename ut, typename st, typename udt, typename sdt> struct int_t;
template <uint32 bit_count, typename ut, typename st, typename udt, typename sdt>
struct basic_info< int_t<bit_count, ut, st, udt, sdt> >
{
static const bool is_signed = true;
static const bool is_integer = true;
static const uint32 num_of_bits = bit_count;
static const uint32 comp_bits = sizeof_ex<ut>::value;
static const type_classes type_class = tc_custom;
static const type_ids type_id = ti_int_t;
};
template <typename t>
inline void mathx_int_setn(t* me)
{
for (uint32 i=0; i < global_int<t>::comp_c; ++i) me->comp[i] = (typename t::ucomp)-1;
}
template <typename t>
inline void mathx_int_setz(t* me)
{
for (uint32 i=0; i < global_int<t>::comp_c; ++i) me->comp[i] = 0;
}
template <typename t, typename u>
inline void mathx_int_iTt(t* me, const u& value)
{
if (sizeof(t) > sizeof(u))
{
if (basic_info<u>::is_signed && ((basic_info<u>::type_id != ti_basic_int && value < global_int<u>::zero) || value < 0))
mathx_int_setn<t>(me);
else
mathx_int_setz<t>(me);
*(u*)me->comp = value;
return;
}
*me = *(t*)&value;
}
template <typename t>
inline void mathx_int_init(t* me, typename t::ucomp hi, typename t::ucomp rest)
{
typedef global_int<t> gint;
for (uint32 i=0; i<gint::comp_c-1; ++i) me->comp[i] = rest;
me->comp[gint::comp_c-1]=hi;
}
template <uint32 bit_count, typename ut, typename st, typename udt, typename sdt>
struct int_t
{
typedef ut ucomp;
typedef st scomp;
typedef udt udcomp;
typedef sdt sdcomp;
typedef int_t<bit_count, ut, st, udt, sdt> t;
typedef global_int<t> gint;
ut comp[gint::comp_c];
int_t() {}
int_t(ut hi, ut rest) { mathx_int_init<t>(this, hi, rest); }
template<typename u>
int_t(const u& value)
{
if (basic_info<u>::is_integer)
mathx_int_iTt<t, u>(this, value);
}
};
typedef int_t<128, mathx_ucomp, mathx_scomp, mathx_udcomp, mathx_sdcomp > int128;
}
和前面的代码在编译下一行时,编译没有问题:
int main()
{
MahtX::int128 q = 1024;
}
现在我想添加支持numeric_limits
类,所以我添加了以下代码(这是类的一部分):
#include <limits>
namespace std
{
using namespace ::MathX;
template < uint32 bit_count, typename ut, typename st, typename udt, typename sdt>
class numeric_limits< int_t< bit_count, ut, st, udt, sdt > >
{
public:
typedef int_t< bit_count, ut, st, udt, sdt > t;
typedef global_int<t> gint;
static const bool is_specialized = true;
static t min() throw() { return gint::minval; }
static t max() throw() { return gint::maxval; }
static const int32 digits = gint::used_t;
static const int32 digits10 = int32(digits * 0.301f);
static const bool is_signed = true;
static const bool is_integer = true;
static const bool is_exact = true;
static const int32 radix = 2;
};
}
:
int main()
{
unsigned b = std::numeric_limits< MathX::int128 >::digits10;
}
GCC编译器产生以下错误:error: incomplete type 'MathX::int_t<128u, unsigned int, int, long long unsigned int, long long int>::gint' used in nested name specifier
.
vc++编译器产生以下错误:error C2039: 'comp_c' : is not a member of 'MathX::global_int<t>'
.
当我从类型global_int
中删除类型t
的变量声明时,随着它们定义的代码编译没有问题,但是这些行必须保留,我既不能解决这个问题,也不能找出为什么会发生。
根据完整的 MSVC10编译错误消息:
unsigned b = std::numeric_limits< MathX::int128 >::digits10;
需要实例化:
template < uint32 bit_count, typename ut, typename st, typename udt, typename sdt>
class numeric_limits< int_t< bit_count, ut, st, udt, sdt > >
{
public:
static const int32 digits = gint::used_t;
static const int32 digits10 = int32(digits * 0.301f);
}
需要实例化:
template<typename t>
struct global_int
{
static const uint32 full_t = is_power_of_2<basic_info<t>::num_of_bits>::value? basic_info<t>::num_of_bits: 0u;
static const uint32 used_t = full_t - int32(basic_info<t>::type_id == ti_int_t);
}
需要实例化:
template <uint32 bit_count, typename ut, typename st, typename udt, typename sdt>
struct int_t
{
typedef global_int<t> gint;
ut comp[gint::comp_c];
}
需要实例化:
template<typename t>
struct global_int
{
static const uint32 full_t = is_power_of_2<basic_info<t>::num_of_bits>::value? basic_info<t>::num_of_bits: 0u;
static const uint32 comp_b = is_power_of_2<basic_info<t>::comp_bits>::value? basic_info<t>::comp_bits: 0;
static const uint32 comp_c = full_t / comp_b;
}
因此,global_int<int_t>
只有在int_t
被实例化后才能被实例化,int_t
只有在global_int<int_t>
被实例化后才能被实例化。这个循环依赖导致它在没有加载最里面的global_int<int_t>
的情况下尝试,导致一个不完整的类型错误。
解决方案(显然)是使int_t
不依赖于global_int<int_t>
。
同样,尽可能避免头文件中的using <namespace>
,并且永远不要在std命名空间内做。这是非法的。
相关文章:
- 使用简单类型列表实现的指数编译时间.为什么
- 为什么与常规GCC不同,即使有"学究性错误",MinGW-GCC也能容忍丢失的返回类型
- 在没有定义返回类型的函数中返回布尔值,并将结果保存在无错误的char编译中-为什么
- 为什么 std::optional::operator=(U&&) 要求你是非标量类型?
- 为什么类中的ostringstream类型的成员会导致";调用隐含删除复制构造函数";错误
- 为什么在我的函数类型后使用引用运算符 (&) 允许我修改它返回的值?
- 非类型指针和引用模板参数,以及在编译时如何/为什么解析它们.c++
- 为什么返回类型中需要typename?C++
- <Windows>为什么 std::thread::native_handle 返回类型为"long long unsigned int"的值,而不是 void*(又名 HANDLE)?
- 为什么 c++(g++) 不允许模板返回类型和函数名称之间有空格?
- 为什么会出现 gettnig 运行时错误:加载类型为"_Bit_type"(stl_bvector.h) 的空指针?
- 为什么返回类型的'const'限定符对标有 __forceinline/内联的函数没有影响?
- 为什么 GCC 在使用类型别名时处理 const reinterpret_cast不同?
- 包含的类类型显然没有声明,为什么?
- 堆栈分配的类类型.为什么两个 ID 实例的地址相同?
- NTTP 的结构类型:为什么所有成员都必须是公共的?
- 为什么 std::bitset 只支持整型数据类型?为什么不支持浮点数?
- C++异常返回类型为什么字符*
- 线程之间的Qt连接类型:为什么这样做
- 无效使用不完整的类型-为什么在这种情况下没有错误