在 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
)。
這種技巧在泛型編程中非常有用,特別是需要處理“可能無返回值”的情況。