在 C++ 中,template<typename R = void>
表示定义一个模板参数 R
,其默认类型为 void
。这意味着:
- 如果用户没有显式指定
R
,则 R
默认为 void
。 - 如果用户显式指定了
R
(如 template<typename R = void>
后面跟着 <int>
),则 R
会被替换为指定的类型(如 int
)。
1. 基本用法
1.1 默认模板参数 void
template<typename R = void> |
class MyClass { |
public: |
using ResultType = R; // 定义一个类型别名 |
}; |
|
int main() { |
MyClass<> obj1; // R 默认为 void |
MyClass<int> obj2; // R 显式指定为 int |
|
// 检查类型 |
static_assert(std::is_same_v<MyClass<>::ResultType, void>); // true |
static_assert(std::is_same_v<MyClass<int>::ResultType, int>); // true |
} |
MyClass<>
使用默认模板参数 void
。MyClass<int>
显式指定 R
为 int
。
1.2 结合函数模板
template<typename R = void> |
R default_value() { |
if constexpr (std::is_void_v<R>) { |
return; // void 返回类型不能有返回值 |
} else { |
return R{}; // 默认构造 R 类型 |
} |
} |
|
int main() { |
default_value(); // R = void,无返回值 |
int x = default_value<int>(); // R = int,返回 0(默认构造) |
} |
- 当
R = void
时,函数不能返回任何值。 - 当
R = int
时,函数返回 int{}
(即 0
)。
2. 常见应用场景
2.1 回调函数(Callback)的默认返回类型
template<typename R = void> |
class Callback { |
public: |
using ReturnType = R; |
|
virtual R execute() = 0; // 纯虚函数 |
}; |
|
// 特化 void 返回类型的情况 |
template<> |
class Callback<void> { |
public: |
void execute() { /* 不需要返回值 */ } |
}; |
- 如果回调函数不需要返回值,可以使用
Callback<>
(默认 void
)。 - 如果需要返回值,可以指定
Callback<int>
等。
2.2 函数对象(Functor)的默认行为
template<typename R = void> |
struct Identity { |
R operator()(R x) { return x; } |
}; |
|
template<> |
struct Identity<void> { |
void operator()(auto x) { /* 不返回任何值 */ } |
}; |
|
int main() { |
Identity<int> id_int; |
int a = id_int(42); // 返回 42 |
|
Identity<> id_void; |
id_void(42); // 无返回值 |
} |
Identity<int>
返回输入值。Identity<>
(即 Identity<void>
)不返回任何值。
2.3 通用函数包装器(类似 std::function
)
template<typename R = void, typename... Args> |
class FunctionWrapper { |
public: |
virtual R invoke(Args... args) = 0; |
}; |
|
// 特化 void 返回类型 |
template<typename... Args> |
class FunctionWrapper<void, Args...> { |
public: |
virtual void invoke(Args... args) = 0; |
}; |
- 如果
R = void
,则 invoke()
不返回任何值。 - 否则,
invoke()
返回 R
类型的值。
3. 与 std::function
的对比
C++ 标准库中的 std::function
也使用了类似的技巧:
std::function<int()> func1; // 返回 int |
std::function<void()> func2; // 返回 void |
std::function<> func3; // 错误!必须指定返回类型 |
std::function
不能省略返回类型(必须显式指定 R
)。- 但自定义模板可以设置默认
R = void
,使 MyFunction<>
合法。
4. 总结
特性 | 说明 |
---|
template<typename R = void> | 定义一个默认类型为 void 的模板参数 |
适用场景 | 回调函数、函数对象、通用包装器 |
与 void 相关的特殊处理 | void 不能用于返回值(如 return; )或构造(如 R{} ) |
C++17 if constexpr 结合 | 可以针对 void 和非 void 类型做不同处理 |
关键点
void
是一个不完整的类型,不能直接实例化(如 void x;
非法)。void
用于函数返回类型时,表示不返回任何值。- 模板默认参数 可以简化代码,避免重复指定常见类型(如
void
)。
这种技巧在泛型编程中非常有用,特别是需要处理“可能无返回值”的情况。