用于在 C++ 中管理平台特定代码的内联命名空间技术

Posted

技术标签:

【中文标题】用于在 C++ 中管理平台特定代码的内联命名空间技术【英文标题】:inline namespace technique for managing platform specific code in c++ 【发布时间】:2016-04-28 11:48:48 【问题描述】:

我已经看到使用 #ifdef 宏(例如 Eigen 库)来管理特定于平台的代码,但还没有看到任何人使用“内联命名空间”来管理特定于平台的代码。

下面的 github repo 给出了具体的代码和示例用法。 https://github.com/dchichkov/curious-namespace-trick/wiki/Curious-Namespace-Trick

我想知道这是否是一种可行的技术,或者是否有任何我看不到的陷阱。下面是代码 sn-p :

#include <stdio.h> 

namespace project  
  // arm/math.h 
  namespace arm  
    inline void add_() printf("arm add\n");  // try comment out 
   

  // math.h 
  inline void add_()  
    // 
    printf("common add\n"); 
    // 
   inline namespace platform inline void add() add_(); 


  inline void dot_()  
    // 
    add(); 
    // 
   inline namespace platform inline void dot() dot_(); 
 

int main()  
 project::dot(); 
 return 1; 
 

输出:

$g++ func.cpp -Dplatform=common ; ./a.out 普通添加

$ g++ func.cpp -Dplatform=arm ; ./a.out 手臂添加

【问题讨论】:

虽然链接到源代码很好,但您还应该在此处复制并粘贴最小的 sn-p 代码(并正确格式化!),以演示您所描述的内容。跨度> 它没有被使用,因为内联命名空间是一个新特性并且没有被广泛支持,但是这种情况是它们存在的主要原因之一。这不是真的好奇或诡计。 @JonathonReinhart 使用代码 sn-p 更新。 @CollinDauphinee 我已经看到它被用于或提到用于版本控制,但不用于选择特定于平台的代码,所以好奇。 你可以在没有inline namespace的情况下做同样的事情。只需制作 commonarm 名称并在那里放置相同的功能。另一种方法是使它们成为类,而不是命名空间。优势 - 您可以共享通用功能并覆盖特定平台(针对每个平台)。 【参考方案1】:

至少有两种方法可以达到相同的效果。第一个带有命名空间。第二个 - 在类中使用静态函数。

使用命名空间:

#include <stdio.h>

namespace GenericMath

    void add();
    void dot();


namespace ArmMath

    void add();

    using GenericMath::dot;


namespace GenericMath

    void add() 
    
        printf("generic add");
    

    void dot() 
    
        Math::add();
        printf("generic dot");
    


namespace ArmMath

    void add() 
    
        printf("arm add");
    

    using GenericMath::dot;


int main()

    Math::dot();
    return 1;

类:

#include <stdio.h>

class GenericMath

public:
    static void add();
    static void dot();
;

class ArmMath : public GenericMath

public:
    static void add();
;

void GenericMath::add() 

    printf("generic add");


void GenericMath::dot() 

  printf("generic dot");
  Math::add();


void ArmMath::add() 

  printf("arm add");


int main()

    Math::add();
    Math::dot();
    return 1;

IMO 内联命名空间会降低代码的可读性并且过于冗长。

【讨论】:

【参考方案2】:

曾经的问题是,与#ifdef 不同,编译器仍会编译所有不适用于当前平台的代码。

因此您不能使用它来处理特定于平台的 API。

【讨论】:

好吧,你不能完全避免预处理器。但是只有预处理器会很麻烦。即使有问题#define 用于选择正确的命名空间。 是的,但是在给定的示例中,预处理器正在选择启用的变体,但仅将其他变体从默认查找集中取出,而不是对编译器完全隐藏它们。在许多情况下,这可能是一件好事(例如,避免在未启用的路径上出现 bitrot),但它确实存在限制。问题特别是内联命名空间与#ifdef 我看不出问题意味着完全避免使用#ifdef。我将其理解为仅预处理器预处理器+内联命名空间。可能作者可以澄清一下吗? 问题是“给定技术的陷阱”。给定的技术依赖内联命名空间来导致静态名称解析以找到所需的特定于平台的代码,并将其与 Eigen 库中 #ifdef 的使用进行对比。

以上是关于用于在 C++ 中管理平台特定代码的内联命名空间技术的主要内容,如果未能解决你的问题,请参考以下文章

C++入门(命名空间缺省参数函数重载引用内联函数)

超详细的C++入门学习(命名空间,缺省参数,内联函数,函数重载等)

C++入门语法第一篇:(命名空间缺省参数函数重载引用内联函数)

C++入门(命名空间,缺省参数,函数重载,引用,内联函数,auto,范围for)

[C/C++]C++的命名空间,缺省参数,引用,auto关键字,内联函数等

C++初阶:入门总结命名空间 | 缺省参数 | 函数重载 | 引用 | 内联函数