-
Notifications
You must be signed in to change notification settings - Fork 256
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Linking errors when used in multiple places #75
Comments
Hello, Thanks for this bug report. Placing these definitions in an anonymous/unnamed namespace makes sense because definition is treated as a definition of a namespace with unique name. Unnamed namespaces as well as all namespaces declared directly or indirectly within an unnamed namespace have internal linkage. Since namespace {
int i; // defines ::(unique)::i
}
void f() {
i++; // increments ::(unique)::i
}
namespace A {
namespace {
int i; // A::(unique)::i
int j; // A::(unique)::j
}
void g() { i++; } // A::unique::i++
}
using namespace A; // introduces all names from A into global namespace
void h() {
i++; // error: ::(unique)::i and ::A::(unique)::i are both in scope
A::i++; // ok, increments ::A::(unique)::i
j++; // ok, increments ::A::(unique)::j
} I've pushed the suggested fix. Please close if if the changes meet your needs. |
Cool, this works for me. I understand tactically how the fix works. I suppose I can even understand why this is needed generally. In this case, where the template variables are always the same value, I was surprised that the linker could not resolve the symbols like it does when two linked libraries both themselves link to a common symbol. But I suppose that had the |
And, of course, thank you for the software, the careful response, and the rapid fix! |
I have encountered a linker error that I do not fully understand, and a workaround which I do not fully understand either.
I am using a pattern where I parse a global
ArgumentParser
in main() (ish) and then pass around my options (by non-const reference) to multiple translation units where the different parts of the program know what their option keys are and can retrieve their specialized values. This pattern requires includingargparse.hpp
in multiple source files so the definition ofArgumentParser
is available in each place it is used. I am compiling with clang 9.0.1.Everything compiles great this way, but fails to link. The problem is that all the template specializations, such as
are multiply defined. Clang only tells me where they are initially defined (exactly one time) but also errors out because they are multiply defined. OK, then:
I find this confusing because I would have thought that
constexpr
would be, well, const, and perhaps not instantiated multiple times in a way that could not be resolved at link. I am noconstexpr
expert though, and clearly something else is happening.I tried using inline:
which, to my constexpr-standard-naive mind looks silly, and indeed this had no effect.
I also tried reducing this to a declaration and defining the specialization exactly once (in a '.cpp' file):
which did not compile. Finally, I found that this guy is onto something: https://stackoverflow.com/a/47982008
who suggested to put these template specializations in an "unnamed namespace", which I think means that each object file gets their own copy and these have distinct names at link (avoiding the duplicate symbols). This worked.
So this is what I think:
constexpr
.argparse
would ideally support being used in multiple object files linked together without too much hassle. I would actually prefer have to linkargparse
and lose the header-only benefits than hack around this linkage problem, but I suspect that we can have both features if we just get this constexpr thing right.So thanks for the great software, but where am I messing this up?
The text was updated successfully, but these errors were encountered: