c++ 命名空间别名踩坑

c++ 命名空间别名踩坑

遇到的问题

在现代c++以前(c++11), 实现别名的主要方式主要是通过typedef关键字实现的.

今天写boost/asio代码的时候, 遇到了这样的一个问题, 催生了我的这篇文章加深我的印象.

// 我想写boost.asio中的内容, 经常使用boost::asio::ip::xxxxxxx.
// 正是因为我是现代c++爱好者, 我使用using而不是typedef导入命名空间别名.
    using asio = boost::asio;
// 诶? 报错了?

出现“命名空间 boost::asio 不能用作类型” 编译错误,因为 asio 是一个命名空间而不是一个类型。

如果想要使用asio::xxxxx写, 你会选择什么样的解决方案呢?

我第一个想到的是

using namespace boost;

我当然可以直接使用asio::xxx, 但是这正确吗? 我深知这样写肯定是不好的, 因为这样会导入整个boost命名空间, 会导致命名空间的一些名称产生冲突.

但是 using asio = boost::asio 编译不通过啊. 后来问了ChatGPT老师, 得到了我需要的答案.

原来是这样解决的吗!

使用typedef/using只能够对类型生效. 对命名空间是不可以的!

正确的做法是 使用namespace关键字

namespace asio = boost::asio;

不知道正在看文章的你们知不知道这样的写法, 反正当时的我是不知道可以使用namespace关键字创建命名空间别名的.

2024.8.19记 觉得又无奈又好笑, 基础知识不牢啊!!


回顾c++的别名系统

在C++中,别名的声明方式可以用于类型、命名空间和模板类型别名。以下是详细的介绍:

1. 类型别名
  • 使用 typedef

    • typedef 是C语言和C++中早期的方式,用来为已有类型创建一个新的名字。
    typedef unsigned long ulong;
    ulong a = 10;
    
  • 使用 using

    • using 语法从C++11引入,是更现代化的一种类型别名声明方式,功能上与 typedef 类似,但语法上更加直观,特别是在声明模板类型别名时。
    using ulong = unsigned long;
    ulong a = 10;
    
2. 命名空间别名
  • 可以为一个命名空间创建一个更短的别名。这对于长命名空间或者避免命名冲突很有帮助。
namespace asio = boost::asio;

asio::io_context io;
3. 模板类型别名
  • C++11 之后,引入了使用 using 关键字来为模板类型创建别名。这比使用 typedef 更加直观,因为 using 支持更复杂的语法。
template<typename T>
using Vec = std::vector<T>;

Vec<int> v;  // 等价于 std::vector<int> v;
  • 使用 typedef 实现模板类型别名较为复杂,且难以阅读,因此 using 通常是更好的选择。
4. 函数指针别名
  • 可以为函数指针创建别名,方便在代码中使用。

使用 typedef

typedef void (*FuncPtr)(int);
void myFunction(int a) {}

FuncPtr fp = myFunction;
fp(10);

使用 using

using FuncPtr = void(*)(int);
void myFunction(int a) {}

FuncPtr fp = myFunction;
fp(10);
5. 嵌套的别名
  • 别名可以嵌套使用,比如为某个复杂类型的某一部分创建别名。
using VecInt = std::vector<int>;
using VecIntIter = VecInt::iterator;


VecInt v = {1, 2, 3};
VecIntIter it = v.begin();
总结
  • typedef 主要用于早期C++代码和C语言中,但不支持模板类型别名的复杂语法。如果是为了适配C语言的代码,可以使用typedef。
  • using 是C++11引入的,更加现代化和灵活,推荐在现代C++代码中使用。
  • 命名空间别名模板类型别名 提供了更简洁和清晰的代码表达方式,特别适用于处理复杂类型和长命名空间。
posted @ 2024-08-19 15:47  QU头  阅读(63)  评论(0编辑  收藏  举报