I have a potential ODR violation happening in a large code base. It's a class template that switches behavior based on a #ifdef in different libraries, but the conflicting libs are likely using different instantiations of the template. As a simplified example:
// foo.h
#ifdef USE_DOUBLE
template <typename T>
struct foo { T* value; double x; };
#else
template <typename T>
struct foo { T* value; };
#endif
struct c;
// a_lib.cpp
#include "foo.h"
struct a { foo<a> m_a; };
struct a_helper { foo<c> m_c; };
// b_lib.cpp
#define USE_DOUBLE
struct b { foo<b> b; };
struct b_helper { foo<c> m_c; };
- I'm guessing that
foo<a>
andfoo<b>
don't have an ODR violation, correct? - But that the differing definitions of
foo<c>
brought in bya_helper
andb_helper
just got incredibly sketchy, correct?
The catch is that I have this in a huge project. Also, it's likely (but not certain) that I have only the equivalent of non-overlapping a
and b
, and not the problematic a_helper
and b_helper
. However, I can't really be sure.
I'm wondering if I can dodge this problem by changing foo to an alias template:
template <typename T>
struct foo_double_impl { T* value; double x; };
template <typename T>
struct foo_impl { T* value; };
#ifdef USE_DOUBLE
template <typename T>
using foo = foo_double_impl<T>;
#else
template <typename T>
using foo = foo_impl<T>;
#endif
- Now, instead of two differing definitions of foo, we now have a definition of foo_impl and foo_double_impl. Does this resolve the ODR violation? Or does the ODR violation persist because there are two different alias templates of foo?