代码之家  ›  专栏  ›  技术社区  ›  enanone

在C++类中有条件启用构造函数[复制]

  •  -1
  • enanone  · 技术社区  · 7 年前

    这个问题已经有了答案:

    我正在学习如何使用 std::enable_if 到目前为止,在我的类中有条件地启用和禁用方法方面,我已经取得了一定程度的成功。我将这些方法模板化为布尔值,并且这些方法的返回类型是 STD::EnableαIF 这样的布尔值。这里的最小工作示例:

    #include <array>
    #include <iostream>
    #include <type_traits>
    
    struct input {};
    struct output {};
    
    template <class io> struct is_input { static constexpr bool value = false; };
    
    template <> struct is_input<input> { static constexpr bool value = true; };
    
    template <class float_t, class io, size_t n> class Base {
    private:
      std::array<float_t, n> x_{};
    
    public:
      Base() = default;
      Base(std::array<float_t, n> x) : x_(std::move(x)) {}
      template <class... T> Base(T... list) : x_{static_cast<float_t>(list)...} {}
    
      // Disable the getter if it is an input class
      template <bool b = !is_input<io>::value>
      typename std::enable_if<b>::type get(std::array<float_t, n> &x) {
        x = x_;
        }
    
      // Disable the setter if it is an output class
      template <bool b = is_input<io>::value>
      typename std::enable_if<b>::type set(const std::array<float_t, n> &x) {
        x_ = x;
        }
    };
    
    int main() {
      Base<double, input, 5> A{1, 2, 3, 4, 5};
      Base<double, output, 3> B{3, 9, 27};
    
      std::array<double, 5> a{5, 6, 7, 8, 9};
      std::array<double, 3> b{1, 1, 1};
    
      // A.get(a);   Getter disabled for input class
      A.set(a);
    
      B.get(b);
      // B.set(b);   Setter disabled for input class
    
      return 0;
    }
    

    但是,我不能将此过程应用于有条件地启用 施工人员 ,因为它们没有返回类型。我试过用模板来反对 STD::EnableαIF 但该类未能编译:

    template <class io> class Base{
    private:
      float_t x_;
    public:
      template <class x = typename std::enable_if<std::is_equal<io,input>::value>::type> Base() : x_{5.55} {}
    }
    

    编译器错误如下:

    In instantiation of ‘struct Base<output>’ -- no type named ‘type’ in  ‘struct std::enable_if<false, void>’
    

    如前所述 in this other post 当实例化一个类temnplate时,它会实例化它的所有成员声明(尽管不一定是它们的定义)。该构造函数的声明格式错误,因此无法实例化类。

    你将如何回避这个问题?感谢您的帮助:)

    编辑:

    我想要如下的东西:

    struct positive{};
    struct negative{};
    
    template <class float_t, class io> class Base{
    private:
      float_t x_;
    public:
      template <class T = io, typename = typename std::enable_if<
                              std::is_same<T, positive>::value>::type>
      Base(x) : x_(x) {}
    
      template <class T = io, typename = typename std::enable_if<
                              std::is_same<T, negative>::value>::type>
      Base(x) : x_(-x) {}
    

    如果可能的话。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Jarod42    7 年前

    对于构造函数有两种方法,因为不能在返回类型中使用它

    默认模板参数:

    template <class io> class Base
    {
    private:
        float_t x_;
    public:
        template <class T = io,
                  typename std::enable_if<std::is_equal<T, input>::value, int>::type = 0>
        Base() : x_{5.55} {}
    };
    

    默认参数:

    template <class io> class Base{
    private:
        float_t x_;
    public:
        template <class T = io>
        Base(typename std::enable_if<std::is_equal<T, input>::value, int>::type = 0) :
            x_{5.55}
        {}
    };
    

    在这种情况下,不能将sfinae用作仅依赖于类参数而不依赖于函数的模板参数的参数。

    为:

    template <class T = io, typename = typename std::enable_if<
                          std::is_same<T, positive>::value>::type>
    Base(x) : x_(x) {}
    
    template <class T = io, typename = typename std::enable_if<
                          std::is_same<T, negative>::value>::type>
    Base(x) : x_(-x) {}
    

    您犯了一个常见的错误:默认模板参数不是签名的一部分,因此您只声明和定义两次

    template <class, typename>
    Base::Base(x);
    

    所以我才用

    typename std::enable_if<std::is_equal<T, input>::value, int>::type = 0
    

    类型在的左侧 = ,所以您将有两个不同的类型,所以有两个不同的签名。