C++模板元编程实现自定义幂函数 负参数分支编译错误求解
编译失败原因
- 重复定义主模板:你注释的代码是重新定义了
hc的主模板,和已有的template <int a, int n> struct hc主模板参数列表不同,属于重复定义同名主模板,C++语法不允许这种写法。你需要实现的是部分特化,而非重新定义主模板。 enable_if用法不符合SFINAE规则:你将enable_if的结果作为第三个模板参数,既没有给默认值,也和主模板的参数数量不匹配,无法被正确匹配到。- 特化优先级冲突:你原有的
n=0特化优先级高于通用分支,当a<0且n=0时会优先匹配n=0的特化返回0,不符合你要求的负数返回-1的规则。
修正后的实现代码
#include <iostream> #include <cmath> #include <type_traits> // 主模板加一个默认的匿名void参数,用于SFINAE筛选 template <int a, int n, typename = void> struct hc { enum { v = a * hc<a, n - 1>::v }; }; // 负数判断的部分特化,优先级高于其他特化,满足条件直接返回-1 template <int a, int n> struct hc<a, n, std::enable_if_t<(a < 0) || (n < 0)>> { enum { v = -1 }; }; // n=1的递归终止特化,只匹配a和n都非负的场景 template <int a> struct hc<a, 1, std::enable_if_t<(a >= 0)>> { enum { v = a }; }; // n=0的特化,只匹配a非负的场景 template <int a> struct hc<a, 0, std::enable_if_t<(a >= 0)>> { enum { v = 0 }; }; int main() { // a^0=0 std::cout << hc<0, 0>::v << " -> 0^0=0\n"; std::cout << hc<3, 0>::v << " -> 3^0=0\n"; // a^n=std::pow std::cout << hc<1, 1>::v << " -> 1^1=" << std::pow(1, 1) << '\n'; std::cout << hc<2, 2>::v << " -> 2^2=" << std::pow(2, 2) << '\n'; std::cout << hc<0, 2>::v << " -> 0^2=" << std::pow(0, 2) << '\n'; std::cout << hc<3, 2>::v << " -> 3^2=" << std::pow(3, 2) << '\n'; std::cout << hc<3, 7>::v << " -> 3^7=" << std::pow(3, 7) << '\n'; // a或n为负时a^n=-1 std::cout << hc<-3, 7>::v << " -> -3^7=-1\n"; std::cout << hc<3, -7>::v << " -> 3^-7=-1\n"; std::cout << hc<0, -7>::v << " -> 0^-7=-1\n"; std::cout << hc<-3, 0>::v << " -> -3^0=-1\n"; }
模板元编程入门资源推荐
- 基础铺垫:先看完《C++ Primer 第5版》第16章的模板相关内容,搞懂模板基础语法、全特化、偏特化、参数推导这些核心概念。
- 系统学习模板:《C++ Templates 第2版》,覆盖从C11到C17的所有模板特性,讲解循序渐进,没有过多的前置知识要求,是公认的模板学习权威入门书。
- 专项学元编程:《C模板元编程》,虽然基于C03编写,但元编程的核心思想、通用技法讲得非常透彻,掌握之后再理解现代C++的
constexpr、concept等特性会非常轻松。
内容的提问来源于stack exchange,提问作者michelson
相关产品推荐
相关产品推荐

