> It will compile and link correctly, but different compilation units will get different results if they take the address of the constant.
Well... I'm assuming there is no need to take the address of an integral constant.
Printable View
> It will compile and link correctly, but different compilation units will get different results if they take the address of the constant.
Well... I'm assuming there is no need to take the address of an integral constant.
>> Well... I'm assuming there is no need to take the address of an integral constant.
From the first post:
>> I don't like the "enum-hack" (for one thing, you can't take the address of it if you need to).
In addition, and someone else can correct me if I'm wrong, but wouldn't a different address mean that the ODR is violated?
That would happen with the original code, with a static variable, would it not?Quote:
If you use an unnamed namespace there will be multiple definitions of the constant in the program. It will compile and link correctly, but different compilation units will get different results if they take the address of the constant. I was under the impression that this is what was trying to be avoided.
>> That would happen with the original code, with a static variable, would it not?
Yes. Which is what I said earlier.
But... who talked about taking the address of the variable? And... what if he does? Wouldn't the address be in scope of whatever unit it was using? If I pass a pointer to a function I'm passing it an address that the function will place in its own scope.
... I really don't see the problem here.
>> But... who talked about taking the address of the variable?
ChaosEngine said (and I already quoted) that the enum-hack was out because you cannot take the address of an enum.
Separately, the different addresses are an indication that different constants are created for each compilation unit. Is this a violation of ODR? Isn't that what the question is all about? Your mention of scope is irrelevent. We're not worried about whether the code will compile and link.
Here is my test code:
Code:// Header.h
#ifndef HEADER_H
#define HEADER_H
#define USE_UNNAMED_NAMESPACE 1
namespace NS
{
#if USE_UNNAMED_NAMESPACE
namespace
{
const int size = 10;
}
#else
enum { size_enum = 10 };
extern int size;
#endif
}
void Test1();
void Test2();
#endif // HEADER_H
Code:// Source1.cpp
#include <iostream>
#include "Header.h"
void Test1()
{
std::cout << "Test1: " << NS::size << ", " << &(NS::size) << '\n';
}
Code:// Source2.cpp
#include <iostream>
#include "Header.h"
void Test2()
{
std::cout << "Test2: " << NS::size << ", " << &(NS::size) << '\n';
}
Change USE_UNNAMED_NAMESPACE to 0 to see it with the enum/extern hack.Code:// main.cpp
#include "Header.h"
#if !USE_UNNAMED_NAMESPACE
int NS::size = NS::size_enum;
#endif
int main()
{
Test1();
Test2();
}
So those are the only two options if you want to be able to take the address of the variable, right? [edit] Or the static keyword, which does the same thing. [/edit]
I don't know if that's the only way. You could also make it a member of a class:This would mean that all compilations would get the same address for the constant, it would be available for sizing of arrays, and it wouldn't require two different names (like the enum-extern hack). I'm not sure if it is standard, though, to allow the initialization of the static const like that. There might also be other issues I haven't thought of or mentioned.Code:struct NS
{
static const int size = 10;
};
>> I'm not sure if it is standard, though, to allow the initialization of the static const like that.
from the standard:
so you're sweet.Quote:
9.4.2.4 If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19). In that case, the member can appear in integral constant expressions.
Well I stand corrected and I have learned something new.