【问题标题】:Explicit specialization of template variable模板变量的显式特化
【发布时间】:2019-10-21 23:19:39
【问题描述】:

类似于 this question 关于模板类的静态 const 类成员的显式特化,以及 this question 关于模板类的显式特化,但我的问题是变量模板的显式特化。

我的 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 修复该问题的方法是什么?

【问题讨论】:

  • 我认为你的constexpr 变量应该是static。其他可能的替代方案:(1) 函数,(2) 静态常量或 (3) enum 值。
  • @Phil1970 static 是我尝试的第一件事,它适用于 clang,但 gcc 给出编译错误:explicit template specialization cannot have a storage class

标签: c++ templates c++14 linker-errors explicit-specialization


【解决方案1】:

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

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

据我了解,是的。根据storage class specifiers cppreference 页面,模板变量应该具有外部链接,即使它是constexpr,这意味着在翻译单元中有多个定义是违反ODR 的。根据该页面底部链接的defect report,“当前的实现似乎提供了与 const 限定变量模板的特化的内部链接”,标准委员会认为这不是他们想要的行为。

针对该问题的 C++14 修复方法是什么?

好像没有。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-16
    • 1970-01-01
    相关资源
    最近更新 更多