vla*_*adr 3 c++ cppunit generic-programming c++11
// my_traits.hpp
#include <stdio.h>
#include <assert.h>
template<typename T>
struct my_traits {
static bool equals(const T& x, const T& y) {
printf("base\n");
return x == y;
}
};
template<typename T>
void my_assert(const T& x, const T& y) {
assert(my_traits<T>::equals(x, y));
}
Run Code Online (Sandbox Code Playgroud)
现在假设库使用如下:
// main.cpp
void my_test1();
void my_test2();
int main() {
my_test1();
my_test2();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
和
// my_test1.cpp
#include "my_traits.hpp"
void my_test1() {
my_assert(-1.0, -1.0);
}
Run Code Online (Sandbox Code Playgroud)
和
//my_test2.cpp
#include "my_traits.hpp"
#ifdef _WIN32
#include <float.h>
#define isnan _isnan
#else
#include <math.h>
#endif
template<>
struct my_traits<double> {
static bool equals(const double& x, const double& y) {
printf("specialization\n");
return x == y || isnan(x) && isnan(y);
}
};
void my_test2() {
my_assert(-1.0, -1.0);
}
Run Code Online (Sandbox Code Playgroud)
现在,
$ g++ main.cpp my_test1.cpp my_test2.cpp && ./a.out
base
base
Run Code Online (Sandbox Code Playgroud)
而
$ g++ main.cpp my_test2.cpp my_test1.cpp && ./a.out
specialization
specialization
Run Code Online (Sandbox Code Playgroud)
当然,无论链接顺序如何,库的用户都希望获得以下结果:
base
specialization
Run Code Online (Sandbox Code Playgroud)
没有专门化或超载(内联)my_assert而不my_traits知道并且知道将相同的专业化注入到my_traits.hpp包含的每个翻译单元是不可接受的(或可维护的),任何人都可以想到另一种技巧,在不修改my_traits.hpp或专门化的情况下实现所需的行为my_assert(或使用kludgy包装类double:))?
§14.7.3[temp.expl.spec]/p6(重点补充):
如果模板,成员模板或类模板的成员是显式专用的,则应在首次使用该特化之前声明该特化,这将导致发生隐式实例化,在发生此类使用的每个翻译单元中 ; 无需诊断.如果程序没有提供显式特化的定义,并且特殊化的使用方式会导致隐式实例化或成员是虚拟成员函数,则程序格式错误,无需诊断.