检测结构包含一个灵活的数组成员
假设我有这样的结构,
struct foo
{
int n;
int values[];
};
可以使用Sfinae检测灵活的数组成员吗?至少,我可以构造一个不能与这种结构实例化的类模板:
template<class T>
struct invalid_with_fam
{
T x;
int unused;
};
如果我尝试创建invalid_with_fam&lt; foo&gt;
:
<source>:14:23: required from here
<source>:11:9: error: flexible array member 'foo::data' not at end of 'struct invalid_with_fam<foo>'
11 | int data[];
| ^~~~
<source>:5:9: note: next member 'int invalid_with_fam<foo>::unused' declared here
5 | int unused;
| ^~~~~~
<source>:2:8: note: in the definition of 'struct invalid_with_fam<foo>'
2 | struct invalid_with_fam
所以现在我想使用该模板,以便我可以禁用任何模板这样的结构。由于这是一个非标准功能,因此我应该提到我针对海湾合作委员会。请注意,我不询问是否可能进行灵活的数组成员。我认为它们是,但希望基于包含此类数组的事实禁用某些模板功能。示例:
template<class T>
void do_stuff(T const& x)
{
//...
y = x; // Slicing would occur here!!!
//...
}
因此,使用do_stuff
与t = foo
使用do_stuff
应该是一个汇编错误。
为此,我认为必须有一种方法来触发无效类型的Sfinae。 Invalid_with_fam&lt; foo&gt;
不存在,因为后面的数据成员将需要不确定的内存布局(未使用
数组的一部分?)。因此,如果SFINAE工作可检测类模板无法实例化,则应起作用。
Say that I have a struct like this
struct foo
{
int n;
int values[];
};
Is it possible to detect the flexible array member using SFINAE? At least, I can construct a class template that cannot be instantiated with such struct:
template<class T>
struct invalid_with_fam
{
T x;
int unused;
};
If I try to create an invalid_with_fam<foo>
:
<source>:14:23: required from here
<source>:11:9: error: flexible array member 'foo::data' not at end of 'struct invalid_with_fam<foo>'
11 | int data[];
| ^~~~
<source>:5:9: note: next member 'int invalid_with_fam<foo>::unused' declared here
5 | int unused;
| ^~~~~~
<source>:2:8: note: in the definition of 'struct invalid_with_fam<foo>'
2 | struct invalid_with_fam
So now I want to use that so I can disable a template for any such struct. Since this is a non-standard feature, I should mention that I target gcc. Notice that I do not ask whether or not flexible array members are possible. I assume they are, but want to disable certain templated functions based on the fact that it contains such arrays. Example:
template<class T>
void do_stuff(T const& x)
{
//...
y = x; // Slicing would occur here!!!
//...
}
Thus, it should be a compilation error to use do_stuff
with T=foo
.
For this to work, I assume that there has to be a way to trigger SFINAE on an invalid type. invalid_with_fam<foo>
cannot exist, because the data member after will require an undefined memory layout (is unused
part of the array or not?). So if SFINAE works to detect that the class template cannot be instantiated it should work.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
C ++没有FAM。编译器对此非标准功能提供的任何支持都可能是不一致的,并且与C ++的其余部分无法很好地集成。
话虽如此,我们可以假装FAM是正常的C ++代码,并尝试使用Sfinae检测它。
不幸的是,它行不通,因为仅在所谓的“立即上下文”中出现错误。该标准没有对“立即上下文”的概念给出定义,但它或多或少(尤其是从此 note ),实例化的类内部不是它。
因此,答案是否定的,使用SFINAE使用类似于
invalid_with_fam
的模板无法检测到它。也许在其他情况下,无法使用FAM结构,并且可以将其嵌入替代的“直接上下文”中,但我不知道任何东西。There are no FAMs in C++. Any support given by the compilers to this non-standard feature is likely to be inconsistent and not integrate well with the rest of C++.
Having said that, we can pretend that a FAM is normal C++ code and try to detect it using SFINAE.
Unfortunately it doesn't work, because only errors in so-called "immediate context" are SFINAE-friendly. The standard does not give a definition to the notion of "immediate context", but it is more or less clear (in particular from this note) that innards of a class being instantiated is not it.
So the answer is no, it is not detectable using SFINAE using a template similar to
invalid_with_fam
. Perhaps there are other contexts in which a FAM struct cannot be used and which can be embedded into the "immediate context" of the substitution, but I am not aware of any.