模板变量的显式特化

Joh*_*qua 5 c++ templates linker-errors explicit-specialization c++14

类似这个问题有关模板类的静态常量类成员明确分工,以及这个问题对模板类的明确分工,但我的问题是具有可变模板的显式特。

我的 MCVE:

//my_templated_literal.h
#pragma once

template <typename T>
constexpr T val;
Run Code Online (Sandbox Code Playgroud)
//my_specialised_literal.h
#pragma once

#include "my_templated_literal.h"

template <>
constexpr int val<int> = 2;
Run Code Online (Sandbox Code Playgroud)
//my_specialised_literal.h
#pragma once

#include "my_templated_literal.h"

template <>
constexpr int val<int> = 2;
Run Code Online (Sandbox Code Playgroud)
//main.cc
#include "my_specialised_literal.h"

int main() {}
Run Code Online (Sandbox Code Playgroud)

编译命令:$CXX -std=c++14 my_specialised_literal.cc main.cc 这可以编译并且似乎在我尝试过的几乎每个编译器版本上都按预期工作,但是会在使用 clang-9 时出现链接器错误:

/tmp/main-ec49c7.o:(.rodata+0x0):`val'的多重定义

/tmp/my_specialised_literal-521691.o:(.rodata+0x0): 这里首先定义

这是大多数编译器版本默默接受的 ODR 违规,还是 clang-9 在某种程度上是错误的?如果是前者,我知道如果我可以使用 C++17,我可以通过进行 specialization 来修复它inline,但是什么是 C++14 修复问题?

Joh*_*qua 2

我想我已经解决了这个问题:

这是大多数编译器版本默认接受的 ODR 违规吗?

据我了解,是的。根据存储类说明符cppreference 页,模板变量应该具有外部链接,即使它是constexpr,这意味着在翻译单元中具有多个定义是 ODR 违规。根据该页面底部链接的缺陷报告,“当前的实现似乎为 const 限定变量模板的专业化提供了内部链接”,标准委员会认为这不是他们想要的行为。

针对此问题的 C++14 修复是什么?

好像没有一个啊