-
Notifications
You must be signed in to change notification settings - Fork 439
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
Use inline variables when available #423
Conversation
I still need to figure out what is going with Basically the whole library compiles fine if I put the inline variable in the |
a25a224
to
964ff9b
Compare
} | ||
#endif // RANGES_CXX_INLINE_VARIABLES | ||
|
||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a utility for building static const objects, not inline variables. The name was right before.
Sounds like a clang bug. IIUC, inline variables shouldn't be changing name lookup. Have you reported it? |
struct static_const | ||
struct | ||
RANGES_DEPRECATED("Use RANGES_CXX_INLINE_VARIABLE instead which supports C++17 inline variables") | ||
static_const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest undeprecating this and removing inline_variable_
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry about that, I didn't knew if static_const
should be deprecated or not. Thought it might be good to alert users that they could be using the macro instead, but static_const
works just fine.
I don't think it is a bug. It actually makes sense to me that the following fails to compile: void foo();
constexpr int foo = 0; // ERROR: foo re-declared as a different kind of symbol The following doesn't fail, but I kind of think it should void foo();
namespace {
constexpr int foo = 0; // OK: foo's are "technically" in different namespaces.
}
// which foo do you mean here? |
But that's not the situation. We have:
There should be nothing wrong with that. |
But I removed the |
But this program:
Gives me:
I thought friend name injection stopped being a thing a long time ago? |
Indeed. No idea. |
struct S {
friend void foo() {}
};
int foo;
int main() {} Will blow up any compiler you point it at because [basic.scope.declarative]/1 seems to imply the opposite:
Since I cannot refer to the function struct S {
friend void foo() {}
};
void foo();
int main() { foo(); } the formerly hidden friend becomes visible, and is in fact the same function. The later text in [basic.scope.declarative] hints at this. Para 3:
and the note after para 4:
Our customization point design "cheats" around this rule by putting the object declaration inside a different namespace, accessed via a using directive (such as an unnamed namespace): struct S {
friend void foo() {}
};
namespace bob { int foo; }
using namespace bob;
int x = foo;
int main() {}
namespace ranges { inline namespace v3 {
struct S {
friend void swap(S&, S&) {}
};
namespace CPOs { inline constexpr int swap = 42; }
using namespace CPOs;
}}
int main() { return ranges::swap; } |
I suggest something like: namespace ranges
{
inline namespace v3
{
namespace function_objects {}
using namespace function_objects;
}
}
#define RANGES_INLINE_VARIABLE(name, type) \
namespace function_objects { inline constexpr type name{}; } |
It seems like |
Apologies for using the ridiculously confusing phrase "non-unnamed namespace" - I meant a normal, named namespace like |
Also, you could try defining it like this: #if RANGES_CXX_INLINE_VARIABLES < RANGES_CXX_INLINE_VARIABLES_17
# if defined(__GNUC__) || defined (__clang__)
# define RANGES_INLINE_VAR extern __attribute__((weak))
# elif defined(_MSC_VER)
# define RANGES_INLINE_VAR extern __declspec(selectany)
# else // Your compiler is hopeless
# define RANGES_INLINE_VAR static
# endif
#else
# define RANGES_INLINE_VAR inline
#endif Then just do: namespace function_objects { RANGES_INLINE_VAR constexpr adl_swap_detail::swap_fn swap{}; } On gcc and clang this should keep ABI compatibility between C++17 and earlier versions, if that were to matter. Of course, |
The last commit:
I've tested this PR with the changes of PR #426 and everything works fine on clang-trunk in C++11/14/1z. Still, I'd block merging this PR till something like #426 gets merged and we start testing clang-trunk on travis again. Question: I don't like this: namespace function_objects {}
using namespace function_objects;
namespace aux
{
namespace function_objects {}
using namespace function_objects;
}
namespace view
{
namespace function_objects {}
using namespace function_objects;
}
namespace action
{
namespace function_objects {}
using namespace function_objects;
}
namespace detail
{
namespace function_objects {}
using namespace function_objects;
} but, does anybody have a better idea? I think I'd rather use an anonymous namespace in the macro: #define RANGES_INLINE_VARIABLE_(type, name, inline_) \
namespace \
{ \
inline constexpr type name{}; \
} |
Does that work? If not, then pls squash this and I'll commit. If so, I think that would be an improvement. |
If you put the definitions in unnamed namespaces, they define distinct objects in each TU, in which case there's no reason to declare them EDIT: And formally, we get ODR violations. |
@ericniebler squashed, let's wait till it passes the tests under clang-trunk. @CaseyCarter Yes, forgot about that. That was a pointless suggestion. We really do need some named namespace. |
I admit I'm not a fan of the name |
|
||
#if RANGES_CXX_INLINE_VARIABLES < RANGES_CXX_INLINE_VARIABLES_17 | ||
#define RANGES_INLINE_VARIABLE_(type, name, inline_) \ | ||
inline_ namespace \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^^ inline_
is used here.
4182dc6
to
4cfcb59
Compare
- adds RANGES_INLINE_VARIABLE(type, name); macro to declare inline variables - deprecates static_const utility on all C++ versions - we should deprecate this for a while since clients might be using it in their own code - adds a detail::inline_variable_ utility equivalent to static_const that is used internally in range-v3 and that clients are not supposed to use
When external linkage entities with definitions in multiple TUs refer to different entities with internal linkage using the same name: constexpr int foo = 42;
inline int& f() { return foo; } |
is used internally in range-v3 and that clients are not supposed to use