基于模板参数值的C++条件模板实现问题求助
基于模板参数x实现不同hello_world,共享bye_world的解决方案
需求描述
基于int类型模板参数x的值调用不同的hello_world函数,但任意x参数都使用同一个bye_world函数。
尝试的实现代码
template_class.hpp
// template_class.hpp template <int x, int y, int z, bool enable> class TemplateClass { public: void hello_world(); void bye_world(); };
template_class.cpp
// template_class.cpp #include <string> #include <iostream> using namespace std; #include "template_class.hpp" template <int x, int y, int z, bool enable> void TemplateClass<x, y, z, x == 1>::hello_world() { std::cout << "hello world from 1" << endl; } template <int x, int y, int z, bool enable> void TemplateClass<x, y, z, x == 2>::hello_world() { std::cout << "hello world from 2" << endl; } template <int x, int y, int z, bool enable> void TemplateClass<x, y, z, enable>::bye_world() { std::cout << "bye world either from 1 or 2" << endl; } template class TemplateClass<1, 1, 1, true>; template class TemplateClass<2, 2, 2, true>;
main.cpp
// main.cpp #include <iostream> #include "template_class.hpp" #include <string> int main() { TemplateClass<1, 1, 1, true> *a = new TemplateClass<1, 1, 1, true>(); TemplateClass<2, 2, 2, true> *b = new TemplateClass<2, 2, 2, true>(); a->hello_world(); b->hello_world(); b->bye_world(); a->bye_world(); return 0; }
编译器报错
# g++ --std=c++11 main.cpp template_class.cpp -o run template_class.cpp:6:82: error: nested name specifier 'TemplateClass<x, y, z, x == 1>::' for declaration does not refer into a class, class template or class template partial specialization template <int x, int y, int z, bool enable> void TemplateClass<x, y, z, x == 1>::hello_world() { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ template_class.cpp:10:82: error: nested name specifier 'TemplateClass<x, y, z, x == 2>::' for declaration does not refer into a class, class template or class template partial specialization template <int x, int y, int z, bool enable> void TemplateClass<x, y, z, x == 2>::hello_world() { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ 2 errors generated.
解决方案
方案1:C++11兼容的成员函数特化
原代码的enable参数是冗余的,直接针对模板参数x对hello_world做成员函数特化即可:
修正后的template_class.hpp
// template_class.hpp template <int x, int y, int z> class TemplateClass { public: void hello_world(); void bye_world(); }; // 特化x=1的hello_world template <int y, int z> void TemplateClass<1, y, z>::hello_world() { std::cout << "hello world from 1" << std::endl; } // 特化x=2的hello_world template <int y, int z> void TemplateClass<2, y, z>::hello_world() { std::cout << "hello world from 2" << std::endl; } // 通用的bye_world实现 template <int x, int y, int z> void TemplateClass<x, y, z>::bye_world() { std::cout << "bye world either from 1 or 2" << std::endl; }
修正后的template_class.cpp(用于分离编译)
// template_class.cpp #include "template_class.hpp" // 显式实例化需要的模板版本 template class TemplateClass<1, 1, 1>; template class TemplateClass<2, 2, 2>;
修正后的main.cpp
// main.cpp #include <iostream> #include "template_class.hpp" int main() { TemplateClass<1, 1, 1> *a = new TemplateClass<1, 1, 1>(); TemplateClass<2, 2, 2> *b = new TemplateClass<2, 2, 2>(); a->hello_world(); b->hello_world(); b->bye_world(); a->bye_world(); delete a; delete b; return 0; }
方案2:C++17及以上使用constexpr if
如果编译器支持C++17,可直接在函数内部用编译期分支判断,无需特化:
template_class.hpp
// template_class.hpp #include <iostream> template <int x, int y, int z> class TemplateClass { public: void hello_world() { if constexpr (x == 1) { std::cout << "hello world from 1" << std::endl; } else if constexpr (x == 2) { std::cout << "hello world from 2" << std::endl; } else { std::cout << "hello world from other" << std::endl; } } void bye_world() { std::cout << "bye world either from 1 or 2" << std::endl; } };
main.cpp只需去掉原代码中的enable参数即可直接使用。
错误原因说明
原代码试图在成员函数定义时用x==1作为模板实参,这不符合C++模板特化语法:类模板的成员函数定义必须对应已声明的类模板或其偏特化版本,而TemplateClass<x, y, z, x==1>并非预先声明的合法偏特化,因此编译器无法识别。
内容的提问来源于stack exchange,提问作者John Karasev
相关产品推荐
相关产品推荐

