c++ - 此代码是否会导致违反单一定义规则?
问题描述
我试图弄清楚在什么情况下以下代码可能会导致违反单一定义规则。
头文件.h
#pragma once
#include <cstddef>
template<typename T, typename U>
class C {
friend std::size_t f() {
// Uses the template parameter that doesn't change
return sizeof(T);
}
friend std::size_t g() {
// Uses the template parameter that does change
return sizeof(U);
}
friend std::size_t h() {
// Does not refer to template parameters
return 0;
}
};
// Declarations to help name lookup
std::size_t f();
std::size_t g();
std::size_t h();
src1.cpp
#include "header.h"
// Cause definintion of f(), g() and h()
template class C<int, double>;
src2.cpp
#include "header.h"
// Cause definintion of f(), g() and h()
template class C<int, float>;
我已经C
在两个不同的翻译单元中明确地实例化了两个不同版本的类模板。如果我将翻译单元链接在一起,是否存在 ODR 违规?
似乎很明显会出现 ODR 违规,g()
因为它在每个翻译单元中都有不同的实现。
但是f()
和h()
呢?每个翻译单元的实现(即令牌流)将保持不变。但它们都隐含地使用C
. 这有什么区别吗?这里没有发生名称查找吗?
解决方案
定义为友元声明一部分的函数隐含地是内联函数,因此只要所有翻译单元中的所有定义都相同,就不会违反 ODR。它不是友元类的成员,而是一个全局函数,类似于将函数声明为友元,然后在类的定义完成后定义内联函数。
就是这种情况 for h
,它不依赖于任何模板参数,以及 for f
,它依赖于模板参数,但该参数int
在您的示例中具有相同的类型 ( )。
函数g
在 src1.cpp 和 src2.cpp 中有不同的定义,因此这是潜在的 ODR 违规。如果函数在两个翻译单元中使用 ODR,这将导致程序格式错误(不需要诊断) 。
推荐阅读
- java - Java 格式日期时间从 "dd/MM/yyyy HH:mm:ss" 到 "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
- html - 为什么不应用此 CSS 规则?
- epplus - 如何将新单元格附加到一行?
- php - 如何求和/获取总价 laravel 上的所有价格
- python-3.x - 定义功能 - 甜甜圈
- javascript - 使用 Vanilla JS 从 ReadableStream 解析 JSON 数据块
- node.js - 遵循 Shopify 的 React 和 Node 教程时出现未处理的运行时错误
- c# - 如何使此名称生成器完全随机
- reactjs - 停止监听更改以存储在 react-redux 中
- javascript - “npm install”不安装任何东西