创建基于 SFINAE 的构造函数时出现编译错误

Compilation error when creating SFINAE based constructor

提问人:Yehonatan 提问时间:8/7/2023 最后编辑:JeJoYehonatan 更新时间:8/7/2023 访问量:60

问:

在实现具有基于 SFINAE 的 ctor 的类期间,我收到下一个错误: 在模板中:'std::enable_if<false, void *>'中没有名为“type”的类型;“enable_if”不能用于禁用此声明

SFINAE 基于之前使用的模板。

代码为:

#include <iostream>
#include <type_traits>

namespace infra {
namespace io {
struct IoDataFrameFactory {};
struct IoDataFrame {};
}


}

template<typename T1, typename T2>
class IoDataFramePair : public infra::io::IoDataFrame {
 public:
  IoDataFramePair(std::istream &is, const infra::io::IoDataFrameFactory &factory,
                  typename std::enable_if_t<(std::is_constructible_v<T1, std::istream &, const infra::io::IoDataFrameFactory &> &&
                      std::is_constructible_v<T2, std::istream &, const infra::io::IoDataFrameFactory &>), void *> = nullptr)
      : first(is, factory), second(is, factory)
  {
      checkSuffix(is);
  }
  
  IoDataFramePair(std::istream &is, const infra::io::IoDataFrameFactory &factory,
                  typename std::enable_if_t<(!std::is_constructible_v<T1, std::istream &, const infra::io::IoDataFrameFactory &>
                      &&
                          std::is_constructible_v<T2, std::istream &, const infra::io::IoDataFrameFactory &>), void *> = nullptr)
      : first(is), second(is, factory)
  {
      checkSuffix(is);
  }
  
  IoDataFramePair(std::istream &is, const infra::io::IoDataFrameFactory &factory,
                  typename std::enable_if_t<(std::is_constructible_v<T1, std::istream &, const infra::io::IoDataFrameFactory &> &&
                      !std::is_constructible_v<T2, std::istream &, const infra::io::IoDataFrameFactory &>), void *> = nullptr)
      : first(is, factory), second(is)
  {
      checkSuffix(is);
  }
  
  IoDataFramePair(std::istream &is, const infra::io::IoDataFrameFactory &factory,
                  typename std::enable_if_t<(!std::is_constructible_v<T1, std::istream &, const infra::io::IoDataFrameFactory &>
                      &&
                          !std::is_constructible_v<T2, std::istream &, const infra::io::IoDataFrameFactory &>), void *> = nullptr)
      : first(is), second(is)
  {
      checkSuffix(is);
  }
 
 private:
  int m_version;
  // Define other members and functions as needed
  
  void checkSuffix(std::istream &is)
  {
      // Implement checkSuffix logic
  }
  
  std::istream m_beginIS;
  std::istream m_middleIs;
  T1 first;
  T2 second;
};

int main()
{
    // Usage example
    std::stringstream is();  // You need to provide an actual input stream
    infra::io::IoDataFrameFactory factory;  // You need to provide an actual IoDataFrameFactory
    
    IoDataFramePair<int, double> pair1(is, factory);  // Calls the appropriate constructor
    IoDataFramePair<int, int> pair2(is, factory);     // Calls the appropriate constructor
    // Similar usage for other cases
    return 0;
}

我做错了什么以及如何解决?

C++ C++17 SFINAE 类模板

评论


答:

2赞 Ted Lyngmo 8/7/2023 #1

您需要使要测试的类型依赖于类型。这里有两种添加方法,默认为 和 。U1U2T1T2

  1. 不向函数添加参数:
template <class U1 = T1, class U2 = T2, std::enable_if_t<
        (std::is_constructible_v<U1, std::istream&,
                                    const infra::io::IoDataFrameFactory&> &&
            std::is_constructible_v<U2, std::istream&,
                                    const infra::io::IoDataFrameFactory&>)>* =
        nullptr>
IoDataFramePair(std::istream& is, const infra::io::IoDataFrameFactory& factory)
    : first(is, factory), second(is, factory) {
    checkSuffix(is);
}
  1. 仍在向函数添加参数:
template<class U1 = T1, class U2 = T2>
IoDataFramePair(
    std::istream& is, const infra::io::IoDataFrameFactory& factory,
    std::enable_if_t<
        (!std::is_constructible_v<U1, std::istream&,
                                    const infra::io::IoDataFrameFactory&> &&
            std::is_constructible_v<U2, std::istream&,
                                    const infra::io::IoDataFrameFactory&>)>* =
        nullptr)
    : first(is), second(is, factory) {
    checkSuffix(is);
}

...并对其他两个构造函数执行相同的操作。

演示 - 注意: 我更喜欢将额外的参数排除在构造函数之外(上面的版本 1),因此我在演示中的所有构造函数中使用了这种方法。


注意:您还有其他问题,例如尝试默认构造 s 并尝试使用 初始化 和 和 a,但我认为这无关紧要。istreamintdoubleistream