Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用模板表示成员之间的约束?_C++_Templates_Types_Constraints_Language Lawyer - Fatal编程技术网

C++ 如何使用模板表示成员之间的约束?

C++ 如何使用模板表示成员之间的约束?,c++,templates,types,constraints,language-lawyer,C++,Templates,Types,Constraints,Language Lawyer,假设我有一个包含一群成员的结构: struct foo { int len; bar *stuff; }; 恰巧stuff将指向一个bars数组,其长度为lenlong。我想用东西的类型对其进行编码。比如: struct foo { int len; DependentLength<bar, &foo::len> stuff; }; structfoo{ 内伦; 依赖长度的材料; }; 然后我可以实现DependentLength,使其行

假设我有一个包含一群成员的结构:

struct foo {
    int len;
    bar *stuff;
};
恰巧
stuff
将指向一个
bar
s数组,其长度为
len
long。我想用
东西
的类型对其进行编码。比如:

struct foo {
    int len;
    DependentLength<bar, &foo::len> stuff;
};
structfoo{
内伦;
依赖长度的材料;
};
然后我可以实现
DependentLength
,使其行为类似于指向条形数组的指针,但在尝试查看大于
foo::len的索引时会断言。但是,我无法实现
DependentLength::operator[]
,因为operator[]只接受一个参数,即索引,它需要知道'foo'对象的位置,以便取消引用成员指针模板参数并执行断言检查

然而,我碰巧知道DependentLength只会在这里作为“foo”的成员使用。我真正想做的是告诉DependentLength相对于自身,而不是相对于foo指针,在哪里可以找到len。所以像
DependentLength之类的东西,但这不是合法的C++。是否有一个好的或失败的邪恶的语言黑客,可以使这项工作

所以像
DependentLength之类的东西

您要求模板根据运行时传递给它们的动态属性执行计算。。。这对模板不起作用,因为它们必须用允许编译在编译时创建模板参数所请求的代码的值进行实例化。因此,传递给模板的任何值都必须在编译时解析,而不是在运行时解析


您必须使用动态容器类型。例如,
std::vector
满足您的请求,如果超出基础容器的边界,则
std::vector::at()
函数将抛出异常。不幸的是,它不像
静态断言
那样方便,但是同样,对于这种情况,使用
静态断言
是不可能的,因为您需要运行时检查边界。此外,
std::vector
还包含一个重载,用于
运算符[]
、迭代器、查询其大小等。

您可以告诉模板要用作长度的成员的偏移量

template<typename T, typename LEN_T, ptrdiff_t LEN_OFFSET>
class DependentArray
{
public:
  T& operator[](LEN_T i_offset)
  {
    if (i_offset < 0) throw xxx;
    if (i_offset > this->size()) throw xxx;
    return this->m_pArr[i_offset];
  } // []
private:
  LEN_T& size()
  {
    return *reinterpret_cast<LEN_T*>(reinterpret_cast<char*>(this) + LEN_OFFSET);
  } // ()
private:
  T* m_pArr;
};

struct foo
{
  int len;
  DependentArray<bar, int, -sizeof(int)> stuff;
};
模板
类依赖项数组
{
公众:
T和运算符[](长度偏移量)
{
如果(i_偏移<0)抛出xxx;
如果(i_offset>this->size())抛出xxx;
返回此->m_pArr[i_offset];
} // []
私人:
长度和尺寸()
{
return*reinterpret\u cast(reinterpret\u cast(此)+LEN\u偏移);
} // ()
私人:
T*m_帕尔;
};
结构foo
{
内伦;
依赖性放射性物质;
};
编辑2:

我想到了另一个解决办法。使用仅适用于foo的类提供大小字段的偏移量,并在定义foo并可以计算偏移量后定义其方法:

#define MEMBER_OFFSET(T,M) \
  (reinterpret_cast<char*>(&reinterpret_cast<T*>(0x10)->M) - \
  reinterpret_cast<char*>(reinterpret_cast<T*>(0x10)))

template<typename T, typename LEN_T, typename SIZE_OFFSET_SUPPLIER> 
class FooDependentArray
{
public:
  T& operator[](LEN_T i_offset)
  {
    if (i_offset < 0) throw xxx;
    if (i_offset > this->size()) throw xxx;
    return this->m_pArr[i_offset];
  } // []
private:
  LEN_T& size()
  {
    const ptrdiff_t len_offest = SIZE_OFFSET_SUPPLIER::getOffset();

    return *reinterpret_cast<LEN_T*>(reinterpret_cast<char*>(this) + len_offset);
  } // ()
private:
  T* m_pArr;
};

struct FooSizeOffsetSupplier
{
    static ptrdiff_t getOffset();
};

struct foo
{
  int len;
  DependentArray<bar, int, FooSizeOffsetSupplier> stuff;
};

ptrdiff_t FooSizeOffsetSupplier::getOffset()
{
  return MEMBER_OFFSET(Foo,m_len) - MEMBER_OFFSET(Foo,m_pArr);
} // ()
#定义成员单位偏移量(T,M)\
(重新解释强制转换(&重新解释强制转换(0x10)->M)-\
重新解释强制转换(重新解释强制转换(0x10)))
模板
类FoodDependentArray
{
公众:
T和运算符[](长度偏移量)
{
如果(i_偏移<0)抛出xxx;
如果(i_offset>this->size())抛出xxx;
返回此->m_pArr[i_offset];
} // []
私人:
长度和尺寸()
{
const ptrdiff_t len_offest=尺寸_OFFSET_供应商::getOffset();
return*reinterpret\u cast(reinterpret\u cast(此)+len\u偏移);
} // ()
私人:
T*m_帕尔;
};
结构FooSizeOffsetSupplier
{
静态ptrdiff_t getOffset();
};
结构foo
{
内伦;
依赖性放射性物质;
};
ptrdiff_t FooSizeOffsetSupplier::getOffset()
{
返回成员偏移量(Foo,m_len)-成员偏移量(Foo,m_pArr);
} // ()

这使得从foo添加和删除成员成为可能。

为什么不首先使用像
std::vector
这样的容器呢?颠倒关系:
struct foo{std::vector bar;int len()const{return bar.size();}实际上我是在打包的结构中查看这个值,以便从线中拉取值,所以我不能仅仅重新排列布局。所以你尝试在C++中植入依赖类型?祝你好运我不是要求模板对运行时值进行操作&foo::len和&foo::stuff都是编译时常量。它们是偏移量,不是绝对地址。到目前为止,这就是我所拥有的,但我希望找到一种不需要我每次向结构中添加新成员时手动更改模板参数的方法。在
size()
member函数中,向指针类型强制转换任意值,然后取消引用它,这样安全吗?此外,返回对临时对象的引用也不安全。我相信您希望将指针投射回
LEN\u T
而不是
LEN\u T*
,然后简单地返回
LEN\u T
而不是
LEN\u T&
@Jason:这不是任意的。他将“this”强制转换为char*,这样指针算法将以字节为单位,然后备份4个字节以查找foo结构中DependentArray前面的int。类型不是
t
?换句话说,假设
这个
的地址是
0x100
,我们减去4个字节得到地址
0xFC
。。。您是说在地址
0xFC
处有一个有效的
int
值,指示数组的大小吗?或者该地址是
T
类型的值?从代码中我可以看到,
0xFC
被强制转换为
LEN_T*
,然后被取消引用,这意味着我们将返回绑定到
0xFC
中包含的对象的引用,而不是实际值
0xFC
@JosephGarvin您是对的,这是该代码的缺点。编写一个宏来计算成员的偏移量非常容易,但是在结构完全定义之前,不能使用它。我开始编写一些使用基类SizeProviderBase和纯虚拟调用getSize()的东西,但后来我不得不将它放在SizeProviderHolder中