C++ 11允许inline namespaces,其所有成员也自动在封闭中namespace.我想不出任何有用的应用 - 有人可以给出一个简短,简洁的例子,说明inline namespace需要哪种情况以及最常用的解决方案?
(另外,当发生了什么并不清楚,我namespace声明inline在一个但不是所有的声明,这可能住在不同的文件.这难道不是找麻烦?)
请考虑以下代码:
#include <iostream>
namespace Foo{
void ool() // Version A
{
std::cout << "Foo::ool" << std::endl;
}
inline namespace Bar{
void ool() // Version B
{
std::cout << "Foo::Bar::ool" << std::endl;
}
}
}
int main()
{
Foo::ool(); // <- error
}
Run Code Online (Sandbox Code Playgroud)
Clang和G ++都正确地标记Foo::ool为含糊不清.我可以Foo::Bar::ool毫无问题地打电话但有没有办法在不改变声明的情况下调用版本A?
我发现处于类似位置的人试图了解会发生什么,但我没有看到这种情况的解决方案.
我处于这种情况,因为我有一个项目,其中包含一个声明,std::__1::pair并std::pair在不同的地方,std::__1作为内联命名空间.我需要代码std::pair明确指向.有解决方案吗?
在C++ - Standard(例如N4594)中,有两种定义operator""s:
namespace std {
...
inline namespace literals {
inline namespace chrono_literals {
// 20.15.5.8, suffixes for duration literals
constexpr chrono::seconds operator"" (unsiged long long);
Run Code Online (Sandbox Code Playgroud)
和string课程:
namespace std {
....
inline namespace literals {
inline namespace string_literals {
// 21.3.5, suffix for basic_string literals:
string operator "" s(const char* str, size_t len);
Run Code Online (Sandbox Code Playgroud)
我想知道从这些命名空间(以及其他所有命名空间std::literals)中获得了什么,如果它们是inline.
我认为它们位于不同的命名空间内,因此它们不会相互冲突.但是当它们存在时inline,这种动机就会消失,对吧?编辑:因为Bjarne解释主要动机是"库版本化",但这不适合这里.
我可以看到"Seconds"和"String"的重载是不同的,因此不会发生冲突.但如果重载相同,它们会发生冲突吗?或者采取(inline?)namespace以某种方式阻止?
因此,他们从中获得了什么inline namespace呢?正如@Columbo在下面指出的那样,如何解决内联命名空间的重载问题,它们是否会发生冲突?
对于大师来说很快:C++ 11允许声明未命名的命名空间inline.这对我来说似乎是多余的; 在未命名的命名空间中声明的事物已经被使用,好像它们是在封闭的命名空间中声明的一样.
所以我的问题是:这是什么意思
inline namespace /*anonymous*/ {
// stuff
}
Run Code Online (Sandbox Code Playgroud)
它与传统的有什么不同?
namespace /*anonymous*/ {
// stuff
}
Run Code Online (Sandbox Code Playgroud)
我们从C++ 98中了解和喜爱?使用时,有人能举出不同行为的例子inline吗?
编辑:只是为了澄清,因为这个问题被标记为重复:我一般不会询问命名内联命名空间.我理解那里的用例,我认为它们很棒.我特别询问将未命名的命名空间声明为什么意思inline.由于未命名的命名空间必然始终是TU的本地命名空间,因此符号版本化似乎并不适用,所以我很好奇添加inline实际上做了什么.
另外,关于未命名的命名空间的标准[7.3.1.1]说:
inline当且仅当它出现在unnamed-namespace-definition中时才会出现
但这对我的非语言律师的眼睛来说似乎是一种重言式 - "它出现在定义中,如果它出现在定义中"!对于奖励积分,任何人都可以解释一下这些标准实际上在说什么吗?
编辑: Cubbi在评论中声称奖励积分:
该标准是说,不具名的命名空间定义的行为就好像它被取代X,其中
inline出现在X当且仅当它出现在未命名的命名空间定义
假设以下代码:
namespace test
{
namespace detail
{
}
inline namespace v1
{
namespace detail
{
void foo()
{
}
}
}
}
int main()
{
test::detail::foo();
}
Run Code Online (Sandbox Code Playgroud)
我们可以看到,这段代码与Clang编译; 然而,与海湾合作委员会没有关系 - 海湾合作委员会抱怨说这namespace detail是不明确的:
main.cpp:20:11: error: reference to 'detail' is ambiguous
test::detail::foo();
^
main.cpp:4:5: note: candidates are: namespace test::detail { }
{
^
main.cpp:10:9: note: namespace test::v1::detail { }
{
^
Run Code Online (Sandbox Code Playgroud)
哪个编译器在这里做正确的事情?
在range-v3中,所有函数都是内联命名空间中的全局函数对象:
Run Code Online (Sandbox Code Playgroud)#if RANGES_CXX_INLINE_VARIABLES < RANGES_CXX_INLINE_VARIABLES_17 #define RANGES_INLINE_VARIABLE(type, name) \ inline namespace function_objects \ { \ inline namespace \ { \ constexpr auto &name = ::ranges::static_const<type>::value; \ } \ } #else // RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17 #define RANGES_INLINE_VARIABLE(type, name) \ inline namespace function_objects \ { \ inline constexpr type name{}; \ } #endif // RANGES_CXX_INLINE_VARIABLES
function_objects命名空间的目的是什么?据我所知,它不会在库中的任何其他位置引用.
C++ 11具有一个称为"内联命名空间"的功能,允许作者在链接时强制执行ABI兼容性,而不会篡改API.例如,来自@HowardHinnant的这些有用的答案解释了如何libc++使用内联命名空间:
我的问题是:boost是否使用了这个C++ 11功能?看起来有些提升开发者至少在考虑最终使用它.但那个线程很老了.它曾经发生过吗?如果是这样,是否适用于所有boost库,或仅适用于子集?
我使用的是Wind River Compiler 4(gcc(C)和g ++(C++)),它可以毫无问题地编译我的所有项目.现在我必须使用Coverity Static Analysis来检查我的代码.我已经配置了特定的编译器.对于C代码(gcc)没有问题,我可以运行分析,但对于C++ - Code(g ++),我遇到了很多错误:
.../c++config.h", line 214: error #40:
expected an identifier
inline namespace __gnu_cxx_ldbl128 { }
^
.../c++config.h", line 214: error #326:
inline specifier allowed on function declarations only
inline namespace __gnu_cxx_ldbl128 { }
^
.../c++config.h", line 214: error #65:
expected a ";"
inline namespace __gnu_cxx_ldbl128 { }
^
.../include/string.h", line 76: error #312:
cannot overload functions distinguished by return type alone
extern __const void *memchr (__const void *__s, int __c, size_t __n) …Run Code Online (Sandbox Code Playgroud) c++ static-analysis coverity-prevent c++11 inline-namespaces
以下情况:
namespace abc{
inline namespace x{
int f() { return 5; }
}
inline namespace y{
int f() { return 6; }
}
int f() { return 7; }
void g(){
x::f(); // okay
y::f(); // okay
f(); // error: ambiguous!
abc::f(); // error: ambiguous!
}
}
Run Code Online (Sandbox Code Playgroud)
GCC 和 clang 同意,这是 GCC 错误消息:
<source>: In function 'void abc::g()':
<source>:16:10: error: call of overloaded 'f()' is ambiguous
16 | f(); // error: ambiguous!
| ~^~
<source>:10:9: note: candidate: 'int abc::f()'
10 …Run Code Online (Sandbox Code Playgroud) 有没有办法模拟inline namespaceMSVC?
LLVM的libc ++使用它来创建一个隐藏的版本化命名空间,如下所示:
#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std {inline namespace _LIBCPP_NAMESPACE {
#define _LIBCPP_END_NAMESPACE_STD } }
#define _VSTD std::_LIBCPP_NAMESPACE
namespace std {
inline namespace _LIBCPP_NAMESPACE {
}
}
Run Code Online (Sandbox Code Playgroud)
并在GCC上仿效它,如下所示:
#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std { namespace _LIBCPP_NAMESPACE {
#define _LIBCPP_END_NAMESPACE_STD } }
#define _VSTD std::_LIBCPP_NAMESPACE
namespace std {
namespace _LIBCPP_NAMESPACE {
}
using namespace _LIBCPP_NAMESPACE __attribute__((__strong__));
}
Run Code Online (Sandbox Code Playgroud)
现在我的问题是,我如何用MSVC实现同样的目标?如果不可能的话,我会很高兴找到一个没有版本化的解决方案(现在),我想这将是
#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std {
#define _LIBCPP_END_NAMESPACE_STD }
#define _VSTD std
Run Code Online (Sandbox Code Playgroud)
但有点失败的目的......
有没有一种简化的方法来包含更多的命名空间,而不是每次都输入相同的东西。这很烦人,尤其是在 .h 文件中。
例如:
而不是写:
int f() {
using namespace blabla1;
using namespace blabla2;
using namespace blabla3;
}
Run Code Online (Sandbox Code Playgroud)
我会选择:
使用 myNamespace = blabla1, blabla2, blabla3;
int f() {
using namespace myNamespace;
/// this will be equivalent to the previous example
}
Run Code Online (Sandbox Code Playgroud)
谢谢
c++ ×11
c++11 ×9
namespaces ×7
c++14 ×2
boost ×1
clang++ ×1
g++ ×1
literals ×1
range-v3 ×1
visual-c++ ×1