类似于这个关于模板类的静态常量类成员的显式专用化的问题,以及这个关于模板类显式专用化的问题,但我的问题是变量模板的显式专用化。
我的MCVE:
//my_templated_literal.h
#pragma once
template <typename T>
constexpr T val;
//my_specialised_literal.h
#pragma once
#include "my_templated_literal.h"
template <>
constexpr int val<int> = 2;
//my_specialised_literal.cc
#include "my_specialised_literal.h"
//main.cc
#include "my_specialised_literal.h"
int main() {}
编译命令:$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,我可以通过使专业化inline
来修复它,但是 C++14 修复问题是什么?
我想我已经解决了这个问题:
这是大多数编译器版本默默接受的 ODR 冲突吗?
据我了解,是的。根据存储类说明符 cppreference 页面,模板变量应该具有外部链接,即使它是constexpr
,这意味着在翻译单元中具有多个定义是违反 ODR 的。根据该页面底部链接的缺陷报告,"当前的实现似乎与符合 const 的变量模板的专业化提供了内部链接",标准委员会认为这不是他们想要的行为。
什么是问题的 C++14 修复程序?
似乎没有。