-
Notifications
You must be signed in to change notification settings - Fork 19
Description
Thanks for putting this library out there. I think it's very cool!
Unfortunately I think there are major UB sharp edges if you use it from multiple translation units. Not sure if you're aware, but since you didn't mention it in the docs I thought maybe you're not.
The root issue is that the value returned by mp::meta<T> is not stable across TUs, because the ID you get depends on the instantiation order.
That in and of itself doesn't necessarily sound like a dealbreaker, just don't pass mp::info across TUs.
But I think it's worse than that. If you ever use mp::meta<T> inside a function that itself is used in two TUs, you get an ODR violation, because that function essentially has two different definitions in the two TUs.
For example:
// foo.h
[[attribute::noinline]] template <typename T> mp::info get_info() { return mp::meta<T>; }
// foo.cc
#include "foo.h"
assert(get_info<int>() == mp::meta<int>);
assert(get_info<float>() == mp::meta<float>);
// bar.cc
#include "foo.h"
assert(get_info<float>() == mp::meta<float>);
assert(get_info<int>() == mp::meta<int>);
In this reproducer, I expect the assertions in foo.cc or in bar.cc to fail (although I didn't actually test it :).
I expect this is a problem in practice only if the function that uses mp::meta<T> itself is not inlined.
Here's a chatgpt conversation that I used to check my work in case it helps, although I expect you're better at C++ than me and don't need it. https://chatgpt.com/share/6941b79f-e1a0-8008-b7f3-d41cc5539d24