C++ 组合模板扩展

标签 c++ templates

我想从图书馆请求一系列数据,这需要我指定两种类型:

class a;
class b;
class c;
template<typename A, typename B> void get() {....}

void get_all() {
  get<a,a>()
  get<a,b>()
  get<a,c>()
  get<b,a>()
  get<b,b>()
  // etc...
}

我想为一组类(大约 10 种不同的变体)的每个组合调用 get 函数 - 这意味着大约 100 次不同的调用。我不想手动编写所有这些 get() 调用的代码。

有什么方法可以自动生成这些调用吗?我想我可以使用预处理器宏,但我很好奇是否有办法生成这样的组合列表,给定 a、b、c、d... 通过使用模板代码。

编辑:小问题:事实上,这一切都在一个成员函数中。

template<typename A, typename B> 
void Getter::get() 
{  
  auto assn = fMemberObject->RetrieveAllDataOfType<association<A,B>();
  .. do stuff with assn ...
}

void Getter::get_all() {
  get<a,a>();
}

因此,代码需要处理传递 this连同模板。 此外,如果可能的话,C++11 可能是我想要插入该语言的极限......

编辑 2: 结果我想避免重复的情况 <a,a><b,b> ...

最佳答案

当对解决模板元编程问题有疑问时,考虑一下如何在正常编程中做到这一点会有所帮助。在这种情况下,我们想要这样的东西:

for a in type_list:
    for b in type_list:
        foo(a,b)

那么,让我们将其直接翻译成 C++。我们需要一种表示类型和类型列表的方法:

template <class T> struct tag { };
template <class... Ts> struct type_list { };

我们需要一种遍历类型列表并为每种类型做一些事情的方法。我们将其称为函数调用。在 C++17 中(在 C++14 及更低版本中,您可以使用 swallow/expander 技巧在每个 f 上调用 tag<Ts>):

template <class... Ts, class F>
void for_each(type_list<Ts...>, F f) {
    (f(tag<Ts>{}), ...);
}

那是……基本上就是这样。我们需要一个实际调用的函数、一个类型列表和代码:

template <class X, class Y>
void foo(tag<X>, tag<Y> ) {
    std::cout << __PRETTY_FUNCTION__ << '\n'; // or something more meaningful
}

int main() {
    type_list<a, b, c> types;

    for_each(types, [=](auto x){
        for_each(types, [=](auto y){
            foo(x, y);
        });});
}

Demo

C++11 version ,某种程度上展示了通用 lambda 的强大功能。


基于希望类型不一样的更新,这样也很容易更新。我们可以在 tag 中添加一个相等运算符:

template <class T, class U>
constexpr std::integral_constant<bool, std::is_same<T,U>::value>
operator==(tag<T>, tag<U> ) { return {}; }

template <class T, class U>
constexpr std::integral_constant<bool, !std::is_same<T,U>::value>
operator!=(tag<T>, tag<U> ) { return {}; }

请注意,我们不会返回 bool ,我们将返回一个在类型系统中对结果进行编码的类型。然后我们可以自然地使用它:

for_each(types, [=](auto x){
    for_each(types, [=](auto y){
        if constexpr (x != y) {
            foo(x, y);
        }
    });});

foo(x,y)仅当两种标记类型不同时才会实例化。

关于C++ 组合模板扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44297950/

相关文章:

C++ 指针和对象实例化

c++ - (相对)C++ 中大小安全的包装 STL 容器

css - JSF 最后添加自定义 css

c++ - (N)RVO 的完整示例

c++ - 在 C++ 中手动重新分配对象数组

c++ - 为什么 std::accumulate 生成 705032704 作为输出而不是 vector 中元素的总和?

c++ - 使用 VS2010 在 "Release"配置中编译 libjson 时出现问题

c++ - 为什么在类外定义类模板的成员函数时需要模板参数?

c++ - 模板函数中 `T::some_typredef` 的类型推断

c++ - 模板函数包装器