模板类模板成员函数enable_if非类型模板参数类外定义报错排查
C14/C17 解决方案
这里提供两种可靠的写法:
方案1:类外定义时显式重复enable_if默认参数
直接在类外定义的模板参数列表中,写出和类内完全一致的enable_if表达式,让编译器能精准匹配类内声明:
#include <type_traits> template <int N> class Foo { public: template <typename = std::enable_if_t<N == 0>> Foo(); template <typename = std::enable_if_t<N == 1>> Foo(int); }; // 正确写法:显式写出默认参数的enable_if表达式 template <int N> template <typename = std::enable_if_t<N == 0>> Foo<N>::Foo() {} template <int N> template <typename = std::enable_if_t<N == 1>> Foo<N>::Foo(int) {} int main() { Foo<0> f0; // 正常编译 Foo<1> f1(42); // 正常编译 }
方案2:将enable_if移到函数参数列表
把enable_if作为构造函数的默认参数,避免默认模板参数的匹配问题,这种写法类内类外定义的风格更统一,也更易读:
#include <type_traits> template <int N> class Foo { public: // 类内声明:用enable_if作为默认参数 Foo(std::enable_if_t<N == 0, int> = 0); Foo(int, std::enable_if_t<N == 1, int> = 0); }; // 类外定义:直接复用参数类型 template <int N> Foo<N>::Foo(std::enable_if_t<N == 0, int>) {} template <int N> Foo<N>::Foo(int, std::enable_if_t<N == 1, int>) {} int main() { Foo<0> f0; // 正常编译 Foo<1> f1(42); // 正常编译 }
C++20 解决方案
C++20的requires表达式彻底简化了这种条件启用的写法,不需要依赖enable_if,类内类外定义的匹配逻辑更直观:
#include <type_traits> template <int N> class Foo { public: Foo() requires (N == 0); Foo(int) requires (N == 1); }; // 类外定义:直接带上requires条件 template <int N> Foo<N>::Foo() requires (N == 0) {} template <int N> Foo<N>::Foo(int) requires (N == 1) {} int main() { Foo<0> f0; // 正常编译 Foo<1> f1(42); // 正常编译 }
内容的提问来源于stack exchange,提问作者oarfish
相关产品推荐
相关产品推荐

