如何解决模板参数顺序引发的C++函数需求冲突?
解决方案:同时支持显式指定元素类型与自动推导
方法1:函数重载
通过提供两个重载版本,分别处理显式指定T和自动推导T的场景:
- 保留原模板函数,用于显式指定
T的情况:
template <typename T, typename Generator> my_container_t<T> generate(size_t size, Generator generator_by_index) noexcept(noexcept(std::declval<Generator>()(0)));
- 添加自动推导
T的重载版本,它会转发到第一个模板函数,并将T推导为生成器的返回类型:
template <typename Generator> auto generate(size_t size, Generator generator_by_index) noexcept(noexcept(std::declval<Generator>()(0))) -> my_container_t<decltype(std::declval<Generator>()(0))> { return generate<decltype(generator_by_index(0)), Generator>(size, generator_by_index); }
两种调用方式均合法:
- 显式指定
T:auto container = generate<char>(size, get_some_int);(匹配第一个模板) - 自动推导
T:auto container = generate(size, my_generator_of_ints);(匹配第二个重载,自动推导T为生成器返回类型)
方法2:默认模板参数(C++11及以上)
调整模板参数顺序,将Generator放在前面,给T设置默认值为生成器的返回类型:
template <typename Generator, typename T = decltype(std::declval<Generator>()(0))> my_container_t<T> generate(size_t size, Generator generator_by_index) noexcept(noexcept(std::declval<Generator>()(0)));
此时:
- 自动推导
T:直接调用generate(size, my_generator_of_ints);,编译器推导Generator并使用默认T - 显式指定
T(C++17及以上支持部分模板参数推导):
若使用C++20,可借助auto container = generate<decltype(get_some_int), char>(size, get_some_int);std::type_identity简化显式指定逻辑:
调用时显式指定#include <type_traits> template <typename T = void, typename Generator> auto generate(size_t size, Generator generator_by_index) noexcept(noexcept(std::declval<Generator>()(0))) -> my_container_t<std::conditional_t<std::is_void_v<T>, decltype(std::declval<Generator>()(0)), T>> { // 实现逻辑 }T:generate<char>(size, get_some_int);
方法1的重载方式兼容性更好,无需依赖高版本C++特性,逻辑也更直观。
内容的提问来源于stack exchange,提问作者einpoklum
相关产品推荐
相关产品推荐

