Similar to this question about explicit specialisation of static const class members of a template class, and this question about explicit specialisation of a template class, but my issue is with explicit specialisation of a variable template.
My 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() {}
Compile command: $CXX -std=c++14 my_specialised_literal.cc main.cc
This compiles and seems to work as expected on just about every compiler version I've tried, but gives linker errors with clang-9:
/tmp/main-ec49c7.o:(.rodata+0x0): multiple definition of `val'
/tmp/my_specialised_literal-521691.o:(.rodata+0x0): first defined here
Is this an ODR violation silently accepted by most compiler versions, or is clang-9 wrong in some way? If the former, I know that if I could use C++17 I could fix it by making the specialisation inline
, but what is a C++14 fix for the problem?
I think I've worked this out:
Is this an ODR violation silently accepted by most compiler versions?
From my understanding, yes. According to the storage class specifiers cppreference page, the template variable should have external linkage, even though it's constexpr
, which means having multiple definitions in a translation unit is an ODR violation. According to the defect report linked at the bottom of that page, "current implementations appear to give internal linkage to specializations of const-qualified variable templates", which was deemed by the standards committee to not be the behaviour they intend.
What is a C++14 fix for the problem?
It seems there isn't one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With