函数模板参数推导:简化依赖推导参数的默认模板参数调用
问题描述
我遇到的问题和另一篇讨论类模板实参推导的帖子类似,但本文聚焦于函数模板实参推导。
目前我有如下代码,允许用户指定方法计算值时使用的算法(因多种无关原因,此处不适用策略模式):
#include <iostream> #include <typeinfo> template<typename T> class BasicStrategy { public: BasicStrategy(T& i_Input) { std::cout << "Applying Basic Strategy to type : " << typeid(T).name() << " With value : " << i_Input <<std::endl; } }; template<typename T> class ComplexStrategy { public: ComplexStrategy(T& i_Input) { std::cout << "Applying Complex Strategy to type : " << typeid(T).name() << " With value : " << i_Input <<std::endl; } }; template<typename T, typename STRATEGY = BasicStrategy<T>> void Func(T& i_Input) { STRATEGY MyStrategy(i_Input); } int main() { int i = 12; double d = 24; Func(i); Func(d); Func<int, ComplexStrategy<int>>(i); Func<double, ComplexStrategy<double>>(d); return 0; }
我希望简化Func()的接口,让用户在不使用BasicStrategy时无需指定冗余类型,理想的调用方式如下:
int main() { int i = 12; double d = 24; Func(i); Func(d); Func<ComplexStrategy>(i); Func<ComplexStrategy>(d); return 0; }
如果把Func声明为:
template<typename STRATEGY, typename T> void Func(T& i_Input)
这样虽然无需重复指定T,但无法设置默认策略,会破坏大量现有代码且降低可读性。
请问是否存在简洁的解决方案,还是只能在这两种方案之间做选择?
解决方案
可以通过模板模板参数实现需求,既保留默认策略,又支持简化调用:
#include <iostream> #include <typeinfo> template<typename T> class BasicStrategy { public: BasicStrategy(T& i_Input) { std::cout << "Applying Basic Strategy to type : " << typeid(T).name() << " With value : " << i_Input << std::endl; } }; template<typename T> class ComplexStrategy { public: ComplexStrategy(T& i_Input) { std::cout << "Applying Complex Strategy to type : " << typeid(T).name() << " With value : " << i_Input << std::endl; } }; // 主模板:使用模板模板参数,默认策略为BasicStrategy template<template<typename> typename STRATEGY = BasicStrategy, typename T> void Func(T& i_Input) { STRATEGY<T> MyStrategy(i_Input); } // 重载版本:兼容原有的调用方式(避免破坏现有代码) template<typename T, typename STRATEGY> void Func(T& i_Input) { STRATEGY MyStrategy(i_Input); } int main() { int i = 12; double d = 24; // 原有调用方式保持不变 Func(i); Func(d); // 简化后的调用方式 Func<ComplexStrategy>(i); Func<ComplexStrategy>(d); // 兼容原来的显式指定两个参数的调用 Func<int, ComplexStrategy<int>>(i); return 0; }
说明
- 主模板使用模板模板参数
template<typename> typename STRATEGY,用户只需传入策略模板本身(如ComplexStrategy),函数会自动推导T并实例化STRATEGY<T>。 - 保留原模板的重载版本,确保现有代码无需修改即可正常工作。
- 这种方式同时满足默认策略需求和简化调用需求,无需在两种方案间妥协。
内容的提问来源于stack exchange,提问作者J.M
相关产品推荐
相关产品推荐

