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

同时接受const和非const对象的C++模板

  •  0
  • user2672165  · 技术社区  · 5 年前

    如何编译以下代码?我想为提供给构造函数的c样式数组和std::数组支持constness的所有变体。

    #include <cstddef>
    #include <array>
    
    template <typename T>
    class Base
    {
     public:
        explicit Base(T* data) : data_(data) {}
    
     private:
        T* data_;
    };
    
    template <typename T, std::size_t S>
    class A : public Base<T>
    {
     public:
        explicit A(T (&array)[S]) : Base<T>(array) { ; }
    
        template <template <typename, std::size_t> class C>
        explicit A(C<T, S>& c) : Base<T>(c.begin())
        {
            ;
        }
    
        template <template <typename, std::size_t> class C>
        explicit A(C<T, S> const& c) : Base<T>(c.begin())
        {
            ;
        }
    };
    
    int main()
    {
        constexpr std::size_t size{5U};
        int c_style_array[size] = {2, 6, 7, 8, 3};
        A<int, size> a(c_style_array);  // OK
        int const c_style_array_const[size] = {2, 6, 7, 8, 3};
        A<int const, size> b(c_style_array_const);  // OK
    
        std::array<int, size> std_array = {2, 6, 7, 8, 3};
        A<int, size> c(std_array);  // OK
        std::array<int const, size> std_array_const_1 = {2, 6, 7, 8, 3};
        A<int const, size> d(std_array_const_1);  // OK
        std::array<int const, size> const std_array_const_2 = {2, 6, 7, 8, 3};
        A<int const, size> e(std_array_const_2);  // OK
        std::array<int, size> const std_array_const_3 = {2, 6, 7, 8, 3};
        A<int, size> f(std_array_const_3);  // NOT OK
    }
    

    错误消息:

    *a.cpp: In instantiation of ‘A<T, S>::A(const C<T, S>&) [with C = std::array; T = int; long unsigned int S = 5]’:
    a.cpp:46:37:   required from here
    a.cpp:26:53: error: invalid conversion from ‘std::array<int, 5>::const_iterator {aka const int*}’ to ‘int*’ [-fpermissive]
         explicit A(C<T, S> const& c) : Base<T>(c.begin())
                                                         ^
    a.cpp:7:14: note:   initializing argument 1 of ‘Base<T>::Base(T*) [with T = int]’
         explicit Base(T* data) : data_(data) {}*
    

    我更喜欢使用 ,但我对使用

    0 回复  |  直到 5 年前
        1
  •  0
  •   max66    5 年前

    以下声明

    std::array<int, size> const std_array_const_3 = {2, 6, 7, 8, 3};
    A<int, size> f(std_array_const_3);  // NOT OK
    

    不起作用,因为 A<int, size> Base<int> 包含 int * std_array_const_3.begin() 返回一个常量迭代器 int const * .

    内景* 用一个 内部常量*

    在我看来 f 应该是一个 A<int const, size> <int,大小> . 不幸的是 无法从 std::array<int, size> const .

    所以我想补充一下 A ,以下构造函数来管理此特殊情况

    template <template <typename, std::size_t> class C,
              typename U = typename std::remove_const<T>::type>
    explicit A(C<U, S> const & c) : Base<T>(c.begin())
     { }
    

    std::remove_const

    另一种方法是修改 C<T, S> const & 构造函数匹配两种情况,如下所示

    template <typename U, template <typename, std::size_t> class C,
              std::enable_if_t<std::is_same_v<U const, T const>, bool> = true>
    explicit A(C<U, S> const & c) : Base<T>(c.begin())
     { }
    

    也适用于 std::enable_if_t std::is_same_v 我想你应该能够构造C++ 98/C++ 03的替代品。

        2
  •  0
  •   user2672165    5 年前

    #include <cstddef>
    #include <array>
    template <typename T>
    class Base
    {
     public:
        explicit Base(T* data) : data_(data) {}
    
     private:
        T* data_;
    };
    
    template <typename U, std::size_t S>
    class A : public Base<U>
    {
     public:
        template<typename T>
        explicit A(T (&array)[S]) : Base<T>(array) { ; }
    
        template <typename T, template <typename, std::size_t> class C>
        explicit A(C<T, S>& c) : Base<T>(c.begin())
        {
            ;
        }
    
        template <typename T, template <typename, std::size_t> class C>
        explicit A(C<T, S> const& c) : Base<T const>(c.begin())
        {
            ;
        }
    };
    int main()
    {
        constexpr std::size_t size{5U};
        int c_style_array[size] = {2, 6, 7, 8, 3};
        A<int, size> a(c_style_array);  // OK
        int const c_style_array_const[size] = {2, 6, 7, 8, 3};
        A<int const, size> b(c_style_array_const);  // OK
    
        std::array<int, size> std_array = {2, 6, 7, 8, 3};
        A<int, size> c(std_array);  // OK
        std::array<int const, size> std_array_const_1 = {2, 6, 7, 8, 3};
        A<int const, size> d(std_array_const_1);  // OK
        std::array<int const, size> const std_array_const_2 = {2, 6, 7, 8, 3};
        A<int const, size> e(std_array_const_2);  // OK
        std::array<int, size> const std_array_const_3 = {2, 6, 7, 8, 3};
        A<int const, size> f(std_array_const_3);  // OK
    }