CodeNebula
C++11stlintermediate

std::make_signed/make_unsigned (C++11 Addition)

C++11 · Modern Revolution · Compiler flag: -std=c++11

Explanation

Converts an integral type to its signed or unsigned counterpart while preserving size, enabling safe conversions in generic code.

Real-World Scenario

Convert a container size type to a signed type for safe subtraction in index calculations.

Quick Snippet

snippet.cpp
#include <type_traits>
using S = std::make_signed<unsigned int>::type; // int
using U = std::make_unsigned<int>::type; // unsigned int

Full Example

make_signed_unsigned.cpp
// CodeNebula - C++11 Example: make_signed_unsigned
// Compile: g++ -std=c++11 -Wall -Wextra -o example make_signed_unsigned.cpp

// Demonstrates std::make_signed and std::make_unsigned to convert
// between signed and unsigned variants of integer types.

#include <iostream>
#include <type_traits>
#include <cstdint>

int main() {
    std::cout << "=== std::make_signed / std::make_unsigned ===" << std::endl;

    // make_unsigned: signed -> unsigned
    using UnsignedInt = std::make_unsigned<int>::type;
    using UnsignedChar = std::make_unsigned<char>::type;
    using UnsignedLong = std::make_unsigned<long long>::type;

    static_assert(std::is_same<UnsignedInt, unsigned int>::value, "int -> unsigned int");
    static_assert(std::is_same<UnsignedLong, unsigned long long>::value, "ll -> ull");

    std::cout << "make_unsigned<int> is unsigned int:            "
              << std::is_same<UnsignedInt, unsigned int>::value << std::endl;
    std::cout << "make_unsigned<char> is unsigned char:          "
              << std::is_same<UnsignedChar, unsigned char>::value << std::endl;
    std::cout << "make_unsigned<long long> is unsigned long long: "
              << std::is_same<UnsignedLong, unsigned long long>::value << std::endl;

    // make_signed: unsigned -> signed
    using SignedUint = std::make_signed<unsigned int>::type;
    using SignedSize = std::make_signed<size_t>::type;

    static_assert(std::is_same<SignedUint, int>::value, "unsigned int -> int");

    std::cout << "\nmake_signed<unsigned int> is int: "
              << std::is_same<SignedUint, int>::value << std::endl;
    std::cout << "make_signed<size_t> is signed:    "
              << std::is_signed<SignedSize>::value << std::endl;

    // Practical: safe conversion
    unsigned int big = 4000000000u;
    auto signed_val = static_cast<std::make_signed<decltype(big)>::type>(big);
    std::cout << "\nunsigned: " << big << std::endl;
    std::cout << "signed:   " << signed_val << " (overflow expected)" << std::endl;

    // Size is preserved
    std::cout << "\nsizeof(int): " << sizeof(int)
              << " == sizeof(make_unsigned<int>): "
              << sizeof(std::make_unsigned<int>::type) << std::endl;

    std::cout << "\nAll checks passed!" << std::endl;
    return 0;
}

// Expected output:
// === std::make_signed / std::make_unsigned ===
// make_unsigned<int> is unsigned int:            1
// make_unsigned<char> is unsigned char:          1
// make_unsigned<long long> is unsigned long long: 1
//
// make_signed<unsigned int> is int: 1
// make_signed<size_t> is signed:    1
//
// unsigned: 4000000000
// signed:   -294967296 (overflow expected)
//
// sizeof(int): 4 == sizeof(make_unsigned<int>): 4
//
// All checks passed!
Run command
g++ -std=c++11 -Wall -Wextra -o example make_signed_unsigned.cpp