在模板元编程中定义自定义类型
Defining custom types in template metaprogramming
我在某个视频中找到了以下代码,我非常感兴趣。
#include <iostream>
using namespace std;
#define LIST1(T1) Node<T1,Null>
#define LIST2(T1,T2) Node<T1,LIST1(T2)>
#define LIST3(T1,T2,T3) Node<T1,LIST2(T2,T3)>
#define LIST4(T1,T2,T3,T4) Node<T1,LIST3(T2,T3,T4)>
struct Null { };
template <int X, typename Next>
struct Node {
static const int val = X;
typedef Next Next_;
};
template <typename List>
struct Sum
{
static const int sum = List::val + Sum<typename List::Next_>::sum;
};
template <>
struct Sum<Null> {
static const int sum = 0;
};
int main()
{
cout << Sum<LIST4(2, 2, 3, 4)>::sum << endl;
}
我的问题是,更好的方法是什么?我还有什么其他方法可以进行类似的解析?我看到的主要问题是用于定义类型的预处理器指令。还有其他方法可以做到这一点吗?
例如,我想表示与上述相同的 IP 地址:
Sum<IP<120.100.10.20>>
这将解析输入。
此外,如果可以从文件中获取它,它会更有用。我认为应该允许这种格式化的数据作为TMP中的类型。我将如何修改代码以支持这一点?
编辑 :: 添加另一个代码,让我觉得它会很有用。
#include <iostream>
#define LIST1(T1) Node<T1,Null>
#define LIST2(T1,T2) Node<T1,LIST1(T2)>
#define LIST3(T1,T2,T3) Node<T1,LIST2(T2,T3)>
#define LIST4(T1,T2,T3,T4) Node<T1,LIST3(T2,T3,T4)>
using namespace std;
// Highest bit in an IP address
template <typename List, int N, bool B>
struct highestBitSet
{
static const bool b = List::val & (1 << N);
static const int bit = highestBitSet<List, N - 1, b>::bit;
};
template <typename List, int N>
struct highestBitSet<List,N,true>
{
static const int bit = N+1;
};
template <typename List>
struct highestBitSet<List, -1, false>
{
static const int bit = 8+highestBitSet<List::Next_, 7, false>::bit;
};
template <int X>
struct highestBitSet<Null, X, false>
{
static const int bit = 0;
};
int main()
{
// Will print 0
cout << highestBitSet<LIST4(1, 0, 0, 0), 7, false>::bit << endl;
// WIll print 31
cout << highestBitSet<LIST4(0, 0, 0, 255), 7, false>::bit << endl;
return 0;
}
使用 C++17我的问题是,更好的方法是什么?我还有什么其他方法可以进行类似的解析?我看到的主要问题是用于定义类型的预处理器指令。还有其他方法可以做到这一点吗?
的折叠表达式,如果 C++17 不可用,则使用 C++14 constexpr
:
#include <iostream>
template<int... N> int_list { };
template<int... N> int_list<N...> list() { return {}; }
template<int... N>
int sum(int_list<N...>)
{
#if __cplusplus > 201402L
return (N + ...);
#else
const int vals[] = { N... };
int sum = 0;
for (auto v : vals)
sum += v;
return sum;
#endif
}
int main()
{
std::cout << sum( list<2, 2, 3, 4>() ) << std::endl;
}
例如,我想表示与上述相同的 IP 地址:
Sum<IP<120.100.10.20>>
这将解析输入。
IPv4 地址不需要可变长度列表,它始终包含四个组件。而且您显示的代码不进行任何解析...那将是一个完全不同的问题。将四个单独的参数传递给宏或函数(如 LIST4(120, 100, 10, 20)
)与编写甚至不是有效C++令牌的120.100.10.20
完全不同。
此外,如果可以从文件中获取它,它会更有用。我认为应该允许这种格式化的数据作为TMP中的类型。我将如何修改代码以支持这一点?
从文件中读取数据是一种运行时效果,不能将模板(编译时)与 I/O(运行时)结合使用。
相关文章:
- Android Studio:如何在build.gradle中定义自定义宏(针对不同的构建变体),并让原生C / C++
- 如何定义自定义生成配置类型,其中通常是.exe的目标改为 DLL
- C++定义自定义unordered_set的不同方法
- 如何为 std::unordered_set 定义自定义键等效谓词?
- 如何从设备代理定义自定义片段
- 如何定义自定义跨平台size_t类型
- C++ - 定义自定义新建和删除运算符时make_shared
- C++ - 定义自定义析构函数时程序崩溃
- LLDB调试器 - 定义自定义类型显示
- 如何在 Boost Dijkstra 中定义自定义距离
- 为boost哈希映射定义自定义哈希函数
- 在派生类中定义自定义返回类型的受保护方法
- 我可以为我的自定义Qt UI元素定义自定义CSS/QSS属性吗?
- 如何在C++中定义自定义浮点格式(类型)
- 定义自定义扫描运算符
- 在运行时为 std::set 定义自定义比较器
- 如何在 C(++) 中定义自定义错误代码
- 如何为Apache模块定义自定义配置指令
- 声明/定义自定义类定制对象的正确方法
- 为boost中的动态阵列定义自定义步进器