繁体   English   中英

构造函数的类模板参数包扩展

[英]Class template parameter pack expansion for constructors

我想创建一个类模板RestrictedInteger ,它只能用编译时已知的某些值构造。 这就是我手动完成的方法:

// Wrapper
template<int... Is> using IntList = std::integer_sequence<int, Is...>;

// This is my class
template<class intList> class RestrictedInteger;
template<int I1>
class RestrictedInteger<IntList<I1>> {
  const int _i;
public:
  constexpr RestrictedInteger(std::integral_constant<int, I1>) : _i(I1) {}
};
//[...]
template<int I1, I2, I3>
class RestrictedInteger<IntList<I1, I2, I3>> {
  const int _i;
public:
  constexpr RestrictedInteger(std::integral_constant<int, I1>) : _i(I1) {}
  constexpr RestrictedInteger(std::integral_constant<int, I2>) : _i(I2) {}
  constexpr RestrictedInteger(std::integral_constant<int, I3>) : _i(I3) {}
};
//[...] (and so on)

当然,我想使用可变参数模板。 如果这只是合法的

template<int... Is>
class RestrictedInteger<IntList<Is...>> {
  int _i;
public:
  constexpr RestrictedInteger(std::integral_constant<int, Is>) : _i(Is) {}... // ERROR
}

因为我正在使用C ++ 17,我认为它会像这样工作:

template<int... Is>
class RestrictedInteger<IntList<Is...>> {
  int _i;
public:
  template<int I>
  constexpr RestrictedInteger(std::enable_if_t<...||(I==Is), std::integral_constant<int, I>>) : _i(I) {} // syntax error: '...' (Visual Stuio 2019)
};

但显然不是。

有什么想法可以解决这个问题吗?

如果编译失败是一个选项(您不需要编译器来查找其他重载) - 您可以将static_assert放在构造函数中:

#include <type_traits>
#include <utility>

template<int... Is> using IntList = std::integer_sequence<int, Is...>;

template<class intList> class RestrictedInteger;

template<int... Is>
class RestrictedInteger<IntList<Is...>> {
private:
  const int _i;
public:
  template <int I>
  constexpr RestrictedInteger(std::integral_constant<int, I>) : _i(I) 
  {
      static_assert(((I == Is) || ...), "Invalid value");
  }
};

int main()
{
    RestrictedInteger<IntList<1, 2, 3>> i = std::integral_constant<int, 3>();
    RestrictedInteger<IntList<1, 2, 3>> ii = std::integral_constant<int, 6>(); // fails
}

或者使用std::enable_if更详细的解决方案:

#include <type_traits>
#include <utility>

template<int... Is> using IntList = std::integer_sequence<int, Is...>;

template<class intList> class RestrictedInteger;

template<int... Is>
class RestrictedInteger<IntList<Is...>> {
private:
  const int _i;
public:
  template <int I, typename std::enable_if_t<((I == Is) || ...)>* = nullptr>
  constexpr RestrictedInteger(std::integral_constant<int, I>) : _i(I) 
  {
  }
};

int main()
{
    RestrictedInteger<IntList<1, 2, 3>> i = std::integral_constant<int, 3>();
    RestrictedInteger<IntList<1, 2, 3>> ii = std::integral_constant<int, 6>(); // fails
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM