使用`folly :: resizeWithoutInitialization`是否会违反一定义规则?

问题描述 投票:0回答:1

Facebook的Folly库有一个UninitializedMemoryHacks标头,它使用一些非传统的技术来访问类的私有成员。它似乎类似于2010 UninitializedMemoryHacks中描述的方法。

我试图了解如果从多个翻译单元使用blog post by Johannes Schaub是否会导致违反一个定义规则。这个问题特别涉及使用resizeWithoutInitialization function,以在每个翻译单元中生成不同的模板实例。

我将有问题的代码简化为以下最小示例:

header.h

resizeWithoutInitialization

src1.cpp

tag struct declared inside an anonymous namespace

src2.cpp

#pragma once

template<typename T, typename U>
class C {
 friend int f() {
  // Uses the template parameter that doesn't change
  return sizeof(T); 
 }

 friend int g() {
  // Uses the template parameter that does change
  return sizeof(U);
 }

 friend int h() {
  // Does not refer to template parameters
  return 0;
 }
};

// Declarations to help name lookup
int f();
int g();
int h();

我已经在两个不同的翻译单元中实例化了#include "header.h" // Cause definintion of f(), g() and h() template class C<int, double>; 类模板的两个不同版本。如果我将翻译单元链接在一起,是否会违反ODR?

[显然,#include "header.h" // Cause definintion of f(), g() and h() template class C<int, float>; 会违反ODR,因为在每个翻译单元中都有不同的实现。

但是Cg()呢?每个翻译单元之间的实现(即令牌流)将保持不变。但是它们都隐式地使用f()的不同实例。这有什么区别吗?没有名称查找发生在这里吗?

[我相信Folly库使用h()的变体,因为C朋友函数从不实际引用其所在类的f()模板参数。

如果要使用多个翻译单元的detail::unsafeStringSetLargerSizeFollyMemoryDetailTranslationUnitTag变体,会构成对ODR的侵犯吗?

c++ templates friend friend-function one-definition-rule
1个回答
0
投票

定义为好友声明一部分的函数隐式为内联函数,因此只要所有定义在所有翻译单元中都相同,就不会违反ODR。它不是类的成员,而是它的朋友,而是全局函数,类似于将函数声明为朋友,然后在类的定义完成后定义内联函数。

string的情况不依赖于任何模板参数,folly::resizeWithoutInitialization的情况不依赖于模板参数,但是在您的示例中,该参数具有相同的类型(h)。 >

函数f在src1.cpp和src2.cpp中具有不同的定义,因此这可能是违反ODR的行为。这导致程序格式错误(无需诊断)。[[if

该功能在两个翻译单元中都使用ODR。
© www.soinside.com 2019 - 2024. All rights reserved.