gpt4 book ai didi

c++ - 您能否通过类类型上的结构化绑定(bind)违反 ODR

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:27:52 29 4
gpt4 key购买 nike

如果 tuple_size 模板是一个完整的类型,结构化绑定(bind)特性表示它会像分解一样与元组一起使用。当 std::tuple_size 在程序的某一点是给定类型的完整类型而在另一点不完整时会发生什么?

#include <iostream>
#include <tuple>

using std::cout;
using std::endl;

class Something {
public:
template <std::size_t Index>
auto get() {
cout << "Using member get" << endl;
return std::get<Index>(this->a);
}

std::tuple<int> a{1};
};

namespace {
auto something = Something{};
}

void foo() {
auto& [one] = something;
std::get<0>(one)++;
cout << std::get<0>(one) << endl;
}

namespace std {
template <>
class tuple_size<Something> : public std::integral_constant<std::size_t, 1> {};
template <>
class tuple_element<0, Something> {
public:
using type = int;
};
}

int main() {
foo();
auto& [one] = something;
cout << one << endl;
}

(此处转载https://wandbox.org/permlink/4xJUEpTAyUxrizyU)

在上面的程序中,Something 类型在程序的某一点通过公共(public)数据成员进行分解,并在另一点像分解一样回退到元组。我们是否在幕后通过隐式“std::tuple_size 完成”检查违反了 ODR?

最佳答案

我看不出有任何理由相信有问题的程序格式错误。简单地让代码中的某些东西依赖于类型的完整性,然后让其他东西依赖于同一类型的完整性,其中该类型已经完成,并不违反标准。

如果我们有类似的东西就会出现问题

inline Something something;  // external linkage
inline void foo() {
auto& [one] = something;
}

在多个翻译单元中定义,其中,在其中一些中,std::tuple_size<Something>foo 处已经完成已定义,而在其他情况下,则不是。这似乎肯定违反了 ODR,因为实体 onefoo 的不同拷贝中接收不同类型,但是,我实际上无法在标准中找到这样的地方。多个定义合并为一个的标准是:

  • each definition of D shall consist of the same sequence of tokens; and

  • in each definition of D, corresponding names, looked up according to 6.4, shall refer to an entity defined within the definition of D, or shall refer to the same entity, after overload resolution (16.3) and after matching of partial template specialization (17.8.3), except that a name can refer to

    • a non-volatile const object with internal or no linkage if the object

      • has the same literal type in all definitions of D,
      • is initialized with a constant expression (8.20),
      • is not odr-used in any definition of D, and
      • has the same value in all definitions of D,

      or

    • a reference with internal or no linkage initialized with a constant expression such that the reference refers to the same entity in all definitions of D;

    and

  • in each definition of D, corresponding entities shall have the same language linkage; and

  • in each definition of D, the overloaded operators referred to, the implicit calls to conversion functions, constructors, operator new functions and operator delete functions, shall refer to the same function, or to a function defined within the definition of D; and
  • in each definition of D, a default argument used by an (implicit or explicit) function call is treated as if its token sequence were present in the definition of D; that is, the default argument is subject to the requirements described in this paragraph (and, if the default argument has subexpressions with default arguments, this requirement applies recursively) 28 ; and
  • if D is a class with an implicitly-declared constructor (15.1), it is as if the constructor was implicitly defined in every translation unit where it is odr-used, and the implicit definition in every translation unit shall call the same constructor for a subobject of D.

如果这里有一条规则使我的代码格式错误,我不知道它是哪一条。也许该标准需要修改,因为它不可能是允许这样做的。

使程序格式错误的 NDR 的另一种方法涉及使用模板:

template <int unused>
void foo() {
auto& [one] = something;
}
// define tuple_element and tuple_size
foo<42>(); // instantiate foo

这会与 [temp.res]/8.4 冲突,据此

The program is ill-formed, no diagnostic required, if ... the interpretation of [a construct that does not depend on a template parameter] in [the hypothetical instantiation of a template immediately following its definition] is different from the interpretation of the corresponding construct in any actual instantiation of the template

关于c++ - 您能否通过类类型上的结构化绑定(bind)违反 ODR,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48679991/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com