C++ using vs typedef: Type Aliases Quick Comparison

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:

Aspecttypedefusing
SyntaxC styleModern
ReadabilityLowerHigher
Template aliasNoYes
Function pointerAwkwardClear
RecommendationLegacyC++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

SituationPrefer
New C++ codeusing
Shared C headers / legacy rulestypedef OK
Template aliasusing (required)
Complex function pointerusing

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;.


  • 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


  • C++ typedef vs using (deep)
  • C++ name hiding
  • C++ namespaces
  • C++ class templates