如何在编译期检查模板参数数量并实现条件成员函数重载?
编译期检查模板参数数量的实现方案
当然可以实现,下面提供几种适配不同C++版本的可行方案:
方案一:C++17 constexpr if(最简洁)
利用C++17引入的constexpr if,直接在函数内部完成编译期判断:
#include <variant> #include <tuple> template<typename... Types> class Foo { public: auto Bar() { if constexpr (sizeof...(Types) == 1) { // 获取参数包第一个类型并返回默认构造对象 return std::tuple_element_t<0, std::tuple<Types...>>{}; } else { return std::variant<Types...>{}; } } };
方案二:C++11 SFINAE + enable_if
如果需要兼容C++11及更早版本,用SFINAE(替换失败不是错误)结合std::enable_if实现函数重载:
#include <variant> #include <tuple> #include <type_traits> template<typename... Types> class Foo { public: // 参数数量为1时启用该版本 template<std::size_t N = sizeof...(Types), typename = std::enable_if_t<N == 1>> std::tuple_element_t<0, std::tuple<Types...>> Bar() { return {}; } // 参数数量不为1时启用该版本 template<std::size_t N = sizeof...(Types), typename = std::enable_if_t<N != 1>> std::variant<Types...> Bar() { return {}; } };
方案三:C++20 requires表达式
C++20的requires表达式让约束逻辑更直观,直接在函数声明后指定编译期条件:
#include <variant> #include <tuple> template<typename... Types> class Foo { public: auto Bar() requires (sizeof...(Types) == 1) { return std::tuple_element_t<0, std::tuple<Types...>>{}; } auto Bar() requires (sizeof...(Types) != 1) { return std::variant<Types...>{}; } };
测试示例
int main() { Foo<int> single_foo; int val = single_foo.Bar(); // 正确返回int类型 Foo<int, std::string> multi_foo; std::variant<int, std::string> var = multi_foo.Bar(); // 正确返回variant类型 }
内容的提问来源于stack exchange,提问作者Samo Chreno
相关产品推荐
相关产品推荐

