【问题标题】:C++ non-literal type error with if constexpr带有 if constexpr 的 C++ 非文字类型错误
【发布时间】:2022-08-14 17:39:24
【问题描述】:

设置

我定义了两个模板类ContainerAContainerB,如下所示

template <class... T>
  class ContainerA{
  public:
    constexpr explicit ContainerA(T... data) : data_(data...) {}
    constexpr explicit ContainerA(std::tuple<T...> data) : data_(data) {}

    constexpr std::tuple<T...> getDataA() const { return data_; }
    constexpr std::size_t getSize() const { return sizeof...(T); }


  protected:
    const std::tuple<T...> data_;
  };


template <class T>
  class ContainerB{
  public:
    constexpr explicit ContainerB(T data) : data_(data) {}

    constexpr T getDataB() const { return data_; }

  protected:
    const T data_;
  };

以及从上面派生的另一个类:

template <class O, class... I>
  class BiggerContainer : public ContainerA<I...>, public ContainerB<O>  {
  public:
    constexpr explicit BiggerContainer (O dataB, I... dataA) : ContainerA<I...>(data...), ContainerB<O>(dataB) {}
    constexpr explicit BiggerContainer (O dataB, std::tuple<I...> dataA) : ContainerA<I...>(data), ContainerB<O>(dataB) {}
  };

到目前为止效果很好

首先,我想初始化一个std::tuple,即持有上述每个类的一个对象:

constexpr auto tup = std::make_tuple(ContainerA(1,2,3), ContainerB(0), BiggerContainer(0,1,2,3));

接下来,我希望能够在编译时评估 if 语句。据我所知,这可以通过if constexpr 完成。 此 if 语句将检查 ContainerAContainerBBiggerContainer 是否存储在 tup 的某个位置。

template <class T>
struct IsBiggerContainerType: std::false_type {};

template <class... T>
struct IsBiggerContainerType<BiggerContainer<T...>> : std::true_type {};

template <class T>
constexpr bool isBiggerContainerType(T /*var*/) {
  return IsBiggerContainerType<T>();
}

int main() {
  constexpr auto element = std::get<2>(tup);
  if constexpr (isBiggerContainerType(element)) {
    std::cerr << \"Hello World\" << std::endl;
  }
}

到目前为止,所有这些工作都很好!

问题

现在我有一个额外的类Test,它将获得一个类似tup 的元组,然后能够在朋友函数中评估一个类似上面的if constexpr

template <AbovesClassesConcept... PS>
class Test{
public:
  explicit Test(std::tuple<PS...> data) : data_(data) {}

  <template idx = 0>
  friend constexpr void evaluate();

private:
  const std::tuple<PS...> data_;
}

<template idx = 0>
constexpr void evaluate() {
  // ... some tuple iteration stuff that works just fine
    
  constexpr auto element = get<idx>(data_); 
  if constexpr (isBiggerContainer(element)) {
    // ... do something with element
  }

  // ... some other tuple iteration stuff that works just fine
}

当像这样创建Test 的实例时

constexpr auto tup = std::make_tuple(ContainerA(1,2,3), ContainerB(0), BiggerContainer(0,1,2,3));
constexpr Test test(tup);

我收到一个错误:

Constexpr 变量不能有非文字类型 \'const Test<ContainerA<int, int, int>, ContainerB, BiggerContainer<int, int, int, int>>

问题是非常量友元函数还是其他地方有问题?到目前为止我无法弄清楚。任何帮助表示赞赏!提前致谢!

    标签: c++ constexpr if-constexpr


    【解决方案1】:

    我觉得你想多了。另见https://stackoverflow.com/a/31763111/9072753

    #include <type_traits>
    #include <tuple>
    #include <iostream>
    
    template <class T, template <class...> class Template>
    struct is_specialization : std::false_type {};
    template <template <class...> class Template, class... Args>
    struct is_specialization<Template<Args...>, Template> : std::true_type {};
    
    //
    
    template <class... T>
    struct ContainerA {
        constexpr explicit ContainerA(T... data) {}
    };
    
    template <class T>
    struct ContainerB {
        constexpr explicit ContainerB(T d) {}
    };
    
    template <class O, class... I>
    struct BiggerContainer : public ContainerA<I...>, public ContainerB<O>  {
        constexpr explicit BiggerContainer (O dataB, I... dataA) :
            ContainerA<I...>(dataA...),
            ContainerB<O>(dataB) {
    
        }
    };
    
    constexpr std::tuple<ContainerA<int, int, int>, ContainerB<int>,
            BiggerContainer<int, int, int, int>
            > tup = std::make_tuple(
        ContainerA(1,2,3),
        ContainerB(0),
        BiggerContainer(0,1,2,3)
    );
    
    template<int IDX, typename TUPLE>
    using isBiggerContainer = is_specialization<
        std::remove_const_t<std::tuple_element_t<IDX, TUPLE>>,
        BiggerContainer>;
    
    int main() {
        static_assert(is_specialization<std::remove_const_t<std::tuple_element_t<0, decltype(tup)>>, ContainerA>{});
        static_assert(!isBiggerContainer<0, decltype(tup)>{});
        static_assert(!isBiggerContainer<1, decltype(tup)>{});
        static_assert(isBiggerContainer<2, decltype(tup)>{});
    }
    

    这将得到一个元组相似的 tup 然后能够评估

    element 是运行时元素,decltype(element) 是类型。

    if constexpr (is_specialization<decltype(element), BiggerContainer>{}) {
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-05
      • 1970-01-01
      • 2014-03-14
      • 1970-01-01
      • 2018-06-17
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      相关资源
      最近更新 更多