包装任意类型/非类型模板类的模板类

时间:2018-06-27 06:59:03

标签: c++ templates

假设我有一个模板类base和一个类wrapper,其中包含base的实例化成员。我想定义类wrapper,使其依赖于模板参数包,该模板参数包只是“传递”给base的实例化成员。

例如,考虑下面的代码,效果很好。

#include <iostream>

template <int i, int j>
struct base {
  base()
  {
    std::cout << "i is " << i;
    std::cout << " j is " << j << std::endl;
  }
};

template <int... T>
struct wrapper {
  base<T...> a;
};

int main()
{
  wrapper<2, 3> x;
  return 0;
}

预先知道base的所有模板参数均为int,因此在template <int...T>的声明中使用wrapper。这允许有限的灵活性,例如,我可以为base的模板参数定义一些默认值,而无需修改wrapper

但是,如果base取决于类型和非类型模板参数的任意列表,如何将wrapper的模板参数传递给base

例如,如果我知道base的所有模板参数都可以隐式转换为int(而不会丢失!),则可以在以下程序中定义wrapper

#include <iostream>

template <int i, bool j>
struct base {
  base()
  {
    std::cout << "i is " << i;
    std::cout << " j is " << (j ? "true" : "false") << std::endl;
  }
};

template <int... T>
struct wrapper {
  base<T...> a;
};

int main()
{
  wrapper<2, true> x;
  return 0;
}

但是,如果base同时依赖于以下程序中的类型和非类型模板参数,则显然不可能简单地将wrapper的模板参数传递给{{ 1}}:

base

该程序无法编译,因为编译器需要#include <iostream> template <class U, int i, int j> struct base { base() { std::cout << "i is " << i; std::cout << " j is " << j << std::endl; } }; template <class... T> struct wrapper { base<T...> a; }; int main() { wrapper<int, 2, 3> x; // Error! return 0; } 的类型。

有没有一种方法可以编写类wrapper并将其模板参数“传递”给类型为wrapper的成员,无论它们是什么 ?

想法是为base编写一个通用代码,例如,wrapper的模板签名发生更改时,无需修改。

1 个答案:

答案 0 :(得分:1)

有一个解决您的问题的方法。它不是很优雅,需要特定的方法,但是可以在您需要的情况下使用:

onSignIn(googleUser) {
  var profile = googleUser.getBasicProfile();
  console.log('ID: ' + profile.getId()); // Do not send to your backend! Use an ID token instead.
  console.log('Name: ' + profile.getName());
  console.log('Image URL: ' + profile.getImageUrl());
  console.log('Email: ' + profile.getEmail()); // This is null if the 'email' scope is not present.
}

使用C ++ 17时,它的冗长程度可能会降低:

template <class U, class i, class j>
struct base {
  base()
  {
    std::cout << "i is " << i::value;
    std::cout << " j is " << j::value << std::endl;
  }
};

template <class ...T>
struct wrapper {
  base<T...> a;
};

int main()
{
  wrapper<int, std::integral_constant<int, 2>, std::integral_constant<int, 3>> x; //no error now!
  return 0;
}