Skip to content

Last updated:2026-10-12

C++ std::function in Depth

While writing C++ code recently I used is_function, and took the opportunity to look at how it is implemented in the standard library, which raised some questions. We all learned about the three dots ..., but do you know what six dots ...... mean?

Likewise, given a piece of code like this:

template<typename... Args>
struct foo(Args......);

Do you know what it means?

Let's dig into the details together!

1. Six Dots

Six dots are usually called two ellipsis operators. We can split the six dots apart and get the following three cases

template <typename... Args> void foo1(Args......)
template <typename... Args> void foo2(Args... ...)
template <typename... Args> void foo3(Args..., ...)

Now it is easier to read. Let's look at the code of std::is_function.

2. Implementation Details of is_function

The implementation of std::is_function involves a primary template and two partial specializations:

// 主模板,假设提供的类型不是函数类型
template<typename T>
struct is_function : std::false_type {};

// 偏特化,用于正常的函数类型
template<typename Ret, typename... Args>
struct is_function<Ret(Args...)> : std::true_type {};

// 偏特化,用于变参函数类型
template<typename Ret, typename... Args>
struct is_function<Ret(Args......)> : std::true_type {};
  • The primary template assumes the given type is not a function type, and yields std::false_type as the result.
  • The first partial specialization covers normal function types, where Ret denotes the return type and Args... the parameter types. If the given type matches such a function signature, std::true_type is the result.
  • The second partial specialization covers variadic function types, where the ellipsis indicates the function takes a variable number of arguments. Likewise, if the given type matches such a function signature, std::true_type is the result.

3. Usage Example

Finally, here is an example of using std::is_function:

#include <iostream>
#include <type_traits>

int func(int x, int y) { return x + y; }
int vararg_func(int x, ...) { return x; }

int main() {
    std::cout << std::boolalpha;
    std::cout << "Is func a function? " << std::is_function<decltype(func)>::value << std::endl;
    std::cout << "Is vararg_func a function? " << std::is_function<decltype(vararg_func)>::value << std::endl;
    return 0;
}

This will output:

Is func a function? true
Is vararg_func a function? true

Got it? End of this section~

Comments