C++ using vs typedef: Type Aliases Quick Comparison
이 글의 핵심
typedef and using both create type aliases, but syntax and template alias support differ. This post focuses on a quick side-by-side comparison.
This post vs the deep-dive companion
- This post (
cpp-using-typedef): Quick comparison—tables, short code, when to use what. - Deep dive (C++ typedef vs using): Function and member function pointers, template aliases, readability, and longer patterns.
Pick one based on how much detail you need.
What is a type alias?
A type alias gives an existing type a new name. C++03 has typedef; C++11 adds using.
// typedef (C++03)
typedef unsigned long ulong;
typedef std::vector<int> IntVec;
// using (C++11)
using ulong = unsigned long;
using IntVec = std::vector<int>;
Why use aliases?:
- Readability: simplify complex types
- Maintenance: change the underlying type in one place
- Abstraction: hide implementation details
- Portability: unify platform-specific types
// Hard to read without an alias
std::map<std::string, std::vector<std::pair<int, double>>> data;
// Clearer with an alias
using DataMap = std::map<std::string, std::vector<std::pair<int, double>>>;
DataMap data;
typedef vs using:
| Aspect | typedef | using |
|---|---|---|
| Syntax | C style | Modern |
| Readability | Lower | Higher |
| Template alias | No | Yes |
| Function pointer | Awkward | Clear |
| Recommendation | Legacy | C++11+ |
// typedef: verbose
typedef void (*FuncPtr)(int, double);
// using: clear
using FuncPtr = void(*)(int, double);
// typedef: cannot template-alias
template<typename T>
typedef std::vector<T> Vec; // error!
// using: template alias
template<typename T>
using Vec = std::vector<T>;
typedef basics
typedef int Integer;
typedef double Real;
typedef int* IntPtr;
typedef int IntArray[10];
typedef int (*FuncPtr)(int, int);
using basics
using Integer = int;
using Real = double;
using IntPtr = int*;
using IntArray = int[10];
using FuncPtr = int(*)(int, int);
using vs typedef (side by side)
typedef void (*FuncPtr)(int, double);
using FuncPtr = void(*)(int, double);
template<typename T>
using Vec = std::vector<T>;
Practical examples
Example 1: container aliases
#include <vector>
#include <map>
#include <string>
using StringVec = std::vector<std::string>;
using IntMap = std::map<std::string, int>;
using Matrix = std::vector<std::vector<int>>;
Example 2: function pointer type
using Operation = int(*)(int, int);
int add(int a, int b) { return a + b; }
int multiply(int a, int b) { return a * b; }
int calculate(int a, int b, Operation op) {
return op(a, b);
}
Example 3: template aliases
template<typename T>
using UniquePtr = std::unique_ptr<T>;
template<typename T>
using Vec = std::vector<T>;
template<typename K, typename V>
using Map = std::map<K, V>;
Example 4: simplifying callbacks
#include <functional>
#include <vector>
using Callback = std::function<void(int)>;
using CallbackList = std::vector<Callback>;
Member type aliases
template<typename T>
class Container {
public:
using value_type = T;
using reference = T&;
using const_reference = const T&;
using pointer = T*;
using size_type = std::size_t;
private:
std::vector<value_type> data;
public:
void push_back(const_reference value) { data.push_back(value); }
reference operator[](size_type index) { return data[index]; }
size_type size() const { return data.size(); }
};
Namespace alias
namespace very_long_namespace_name {
class MyClass {
public:
void doSomething() {}
};
}
namespace vln = very_long_namespace_name;
Common pitfalls
Pitfall 1: typedef reading order
typedef int* (*FuncPtr)(int);
using FuncPtr = int*(*)(int);
Pitfall 2: template aliases need using
template<typename T>
using Vec = std::vector<T>;
When to use aliases
// Good candidates
using ComplexType = std::map<std::string, std::vector<int>>;
using StringVec = std::vector<std::string>;
template<typename T>
using Ptr = std::unique_ptr<T>;
#ifdef _WIN32
using FileHandle = HANDLE;
#else
using FileHandle = int;
#endif
Platform abstraction pattern
#ifdef _WIN32
using FileHandle = HANDLE;
using SocketHandle = SOCKET;
#else
using FileHandle = int;
using SocketHandle = int;
#endif
Callback types pattern
using ErrorCallback = std::function<void(const std::string&)>;
using SuccessCallback = std::function<void(int)>;
Function pointer aliases (summary)
typedef void (*OldStyle)(int, double);
using NewStyle = void(*)(int, double);
For member pointers, noexcept, and calling conventions, see the deep guide.
Template aliases (summary)
Only using can define a template alias.
template<typename T>
using Vec = std::vector<T>;
Readability and team choice
| Situation | Prefer |
|---|---|
| New C++ code | using |
| Shared C headers / legacy rules | typedef OK |
| Template alias | using (required) |
| Complex function pointer | using |
FAQ
Q1: using vs typedef?
A: using is recommended in C++11+; typedef remains for legacy.
Q2: Performance?
A: None. Aliases are compile-time only.
Q3: Template alias?
A: Only using works for template<typename T> using Vec = std::vector<T>;.
Q4: Namespace alias?
A: Use namespace short = long_name;.
Related reading
- C++ typedef vs using (deep dive)
- C++ namespaces
- C++ template template parameters
Practical tips
Follow compiler warnings, profile before micro-optimizing, and align with team conventions.
Keywords
C++ using, typedef, type alias, template alias, C++11
Related posts
- C++ typedef vs using (deep)
- C++ name hiding
- C++ namespaces
- C++ class templates