如何通过结构的成员推断模板
How to deduce template by struct's member
>假设我有一些结构,每个结构都包含一个枚举作为成员。 我想调用结构体的方法,但取决于结构体的成员,如代码示例中所示:
#include <iostream>
#include <string>
#include <type_traits>
enum class Type{
lowercase = 0,
uppercase
};
struct Low{
static constexpr Type cp = Type::lowercase;
};
struct Up{
static constexpr Type cp = Type::uppercase;
};
template<typename Case, typename=void>
struct Printer
{
void print_g(const std::string& s){
std::cout << "just s: " << s << std::endl;
}
};
template<typename X>
struct Printer<X, std::enable_if_t<X::cp == Type::lowercase, void>>
{
void print_g(const std::string& s){
std::cout << "lowercase " << std::nouppercase << s << std::endl;
}
};
template<typename X>
struct Printer <X, std::enable_if_t<X::cp == Type::uppercase, void>>
{
void print_g(const std::string& s){
std::cout << "uppercase " << std::uppercase << s << std::endl;
}
};
int main()
{
Printer<Low> pl;
pl.print_g("hello1");
Printer<Up> p2;
p2.print_g("hello2");
}
但是这个解决方案对我来说看起来不太优雅。 尤其是第一个模板中的部分类型=void。 只有这样代码才会编译。为什么会这样呢? 对于此模板专业化,是否有更好(更优雅)的解决方案?
在 C++17 中,您可以使用if constexpr
:
template <typename X>
struct Printer
{
void print_g(const std::string& s)
{
if constexpr(X::cp == Type::lowercase)
{
std::cout << "lowercase " << std::nouppercase << s << std::endl;
}
else if constexpr(X::cp == Type::uppercase)
{
std::cout << "uppercase " << std::uppercase << s << std::endl;
}
else
{
std::cout << "just s: " << s << std::endl;
}
}
};
如果您无权访问 C++17,请考虑以下选项:
使用常规
if
...else
声明。在您的示例中,没有需要有条件地编译的代码。在 C++14 中实施
static_if
。以下是我给出的一个演讲,解释了如何做到这一点:在 C++14 中实现static
控制流
您可以完全专注于Low
和Up
Printer
。
template<class Case>
struct Printer
{
void print_g(const std::string& s) {
std::cout << "just s: " << s << std::endl;
}
};
template<>
struct Printer<Low>
{
void print_g(const std::string& s) {
std::cout << "lowercase " << std::nouppercase << s << std::endl;
}
};
template<>
struct Printer<Up>
{
void print_g(const std::string& s) {
std::cout << "uppercase " << std::uppercase << s << std::endl;
}
};
请注意,枚举根本不起作用。如果您需要专门针对枚举,您也可以这样做。
template<Type Case>
struct PrinterHelper
{
void print_g(const std::string& s) {
std::cout << "just s: " << s << std::endl;
}
};
template<>
struct PrinterHelper<Type::lowercase>
{
void print_g(const std::string& s) {
std::cout << "lowercase " << std::nouppercase << s << std::endl;
}
};
template<>
struct PrinterHelper<Type::uppercase>
{
void print_g(const std::string& s) {
std::cout << "uppercase " << std::uppercase << s << std::endl;
}
};
template<class Case>
using Printer = PrinterHelper<Case::cp>;
我可能会选择:
enum struct Casing
{
Lower,
Upper
};
template<Casing>
struct printer;
template<>
struct printer<Casing::Lower>
{
...
};
template<>
struct printer<Casing::Upper>
{
...
};
相关文章:
- 我们可以通过 IPC 传递具有动态管理成员的类对象吗?
- 无法通过指针访问对象的成员
- 什么是更好的做法?通过指针或标识符传递类成员?
- 标准对此指向成员函数类型模板参数有何说明?是我的代码有误,还是 MSVS 16.6 有问题?
- C++通过绑定到引用成员而缩短临时变量寿命?
- 派生的成员 通过指向基、static_cast、crtp、删除模板的指针
- 在 C++ 中通过引用传递类成员时,Const 不起作用
- 如何通过函数指针递归调用类成员函数?
- 通过指针调用模板类成员函数 [为什么这是有效的 c++]?
- "Class1"类"Class2"对象作为私有数据成员。如何通过"Class 2"函数引用"Class1"对象?
- C++::在构造函数退出之前通过指针调用成员函数
- 通过放置 new 重用数据成员存储
- 为什么模板类的成员需要通过其模板类的参数进行参数化
- 成员呼叫通过接线员<<
- 如何使用来自同名父类的成员函数(通过 this->)?
- 子类是否也在 c++ 中继承私有数据成员?但通过超类的公共方法访问
- 指针类成员在通过类方法初始化后保持 NULL
- C 运行时成员函数通过字符串名称访问
- 从外部访问静态成员并通过继承 c++ 访问静态成员
- 类的成员只能通过set和get方法间接访问