One definition rule and specialized template classes

The authors of the popular library decided to implement the following design pattern :

// 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));
}

      

Now, suppose the library is used like this:

// main.cpp
void my_test1();
void my_test2();

int main() {
        my_test1();
        my_test2();
        return 0;
}

      

and

// my_test1.cpp
#include "my_traits.hpp"

void my_test1() {
        my_assert(-1.0, -1.0);
}

      

and

//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);
}

      

Now,

$ g++ main.cpp my_test1.cpp my_test2.cpp && ./a.out
base
base

      

then

$ g++ main.cpp my_test2.cpp my_test1.cpp && ./a.out
specialization
specialization

      

The user of the library will naturally want the following result regardless of the link order:

base
specialization

      

Except for specialization or overloading (inlined) my_assert

instead my_traits

, and knowing that injecting the same specialization into every translation unit where included my_traits.hpp

is not acceptable (or supported) can anyone think of another trick that achieves the desired behavior without changing my_traits.hpp

or specializingmy_assert

(or using the kludgy wrapper class for double

:))?

+3


source to share


1 answer


§14.7.3 [temp.expl.spec] / p6 (emphasis mine):



If a template, template member, or template class member is explicitly specialized, then that specialization must be declared before the first use of that specialization, which is implicitly instantiated, in each translation unit to what such use occurs ; no diagnostics required. If the program does not provide a definition for explicit specialization, and either the specialization is used in such a way that the implicit instantiation or member is a virtual member of the function, the program is ill-formed and does not require diagnostics.

+5


source







All Articles