Helpex - Trao đổi & giúp đỡ Đăng nhập
22

Tôi đã xem xét cách initializer_listtriển khai, vì vậy tôi đã tìm thấy phần 18.9 của tiêu chuẩn và tìm thấy một giao diện đủ đơn giản. Tôi nghĩ rằng sẽ là hướng dẫn để tạo phiên bản của riêng tôi mà tôi đã đặt tên MyNamespace::InitializerListvà một trường hợp sử dụng:

template<class T>
class ArrayPrinter
{
public:
    ArrayPrinter(MyNamespace::InitializerList<T> list)
    {
        for (auto i : list) cout << i << endl;
    }
};

...

ArrayPrinter ap{ {1,2,3} };

Tôi rất ngạc nhiên khi thấy rằng điều này không hoạt động và trình biên dịch phàn nàn rằng nó không thể tìm thấy một hàm tạo phù hợp (nó muốn cung cấp cho tôi 3 đối số nhưng phần 18.9 chỉ mô tả một hàm tạo mặc định).

Sau một hồi loay hoay, tôi thấy rằng lớp của mình phải được đặt tên chính xác thì std::initializer_listmới có thể hoạt động được. Tôi cũng có thể đặt bí danh cho std::initializer_listMyNamespacenhưng tôi không thể đặt bí danh MyNamespace::InitializerListstd::initializer_list.

Có vẻ như đây không thực sự là một tính năng ngôn ngữ vì nó phụ thuộc vào thư viện tiêu chuẩn ?

Điểm chính cho câu hỏi của tôi là tại sao cái tên lại quan trọng như vậy và 3 đối số mà nó đang cố gắng truyền cho hàm tạo là gì?

22 hữu ích 5 bình luận 5.4k xem chia sẻ
25

Cái tên rất quan trọng vì tiêu chuẩn đã nói lên điều đó. Tiêu chuẩn cần một số cách để bạn có thể nói, "phương thức khởi tạo này có thể được chuyển qua một danh sách giằng-init chứa một chuỗi các giá trị kiểu T". Cách đó được đặt tên là " std::initializer_list".

Bạn không thể tạo một lớp có tất cả các thuộc tính ngôn ngữ của initializer_list. Bạn có thể tạo một cái thỏa mãn các điều kiện của loại được chỉ định bởi phần [initializer.list.syn] của tiêu chuẩn. Nhưng bạn sẽ nhận thấy rằng hàm tạo duy nhất được chỉ định có một hàm tạo mặc định . Cách duy nhất để tạo một initializer_listvới các phần tử thực tế dựa vào trình biên dịch , không phải mã đất người dùng.

Vì vậy, bạn không thể sao chép mọi thứ về initializer_list. Cũng như bạn không thể tái tạo std::type_info. Thư viện chuẩn C ++ không phải là tùy chọn .

25 hữu ích 4 bình luận chia sẻ
0

Câu trả lời này không hoàn toàn chính xác. Đó khả năng để tạo ra một đầy đủ chức năng std::initializer_list- nó chỉ cần đáp ứng các yêu cầu cụ thể của trình biên dịch mục tiêu.

Đối với GCC và yêu cầu đó là một ctor riêng. Đây là cách triển khai libc ++ (cũng hoạt động tốt với GCC 8.3):

template<class _Ep>
class initializer_list
{
    const _Ep* __begin_;
    size_t    __size_;
    
    inline
    constexpr
    initializer_list(const _Ep* __b, size_t __s) noexcept
        : __begin_(__b),
          __size_(__s)
    {}
public:
    typedef _Ep        value_type;
    typedef const _Ep& reference;
    typedef const _Ep& const_reference;
    typedef size_t    size_type;
    
    typedef const _Ep* iterator;
    typedef const _Ep* const_iterator;
    
    inline
    constexpr
    initializer_list() noexcept : __begin_(nullptr), __size_(0) {}
    
    inline
    constexpr
    size_t    size()  const noexcept {return __size_;}
    
    inline
    constexpr
    const _Ep* begin() const noexcept {return __begin_;}
    
    inline
    constexpr
    const _Ep* end()   const noexcept {return __begin_ + __size_;}
};

template<class _Ep>
inline
constexpr
const _Ep*
begin(initializer_list<_Ep> __il) noexcept
{
    return __il.begin();
}

template<class _Ep>
inline
constexpr
const _Ep*
end(initializer_list<_Ep> __il) noexcept
{
    return __il.end();
}
0 hữu ích 0 bình luận chia sẻ
0

Tôi đã tìm thấy bài đăng này khi tôi gặp sự cố khi tự mình triển khai initializer_list và thấy rất hữu ích khi viết phiên bản của riêng tôi để biên dịch trên msvc, gcc, avr-gcc và clang. Câu hỏi này có thể cũ nhưng tôi muốn chia sẻ giải pháp của mình với hy vọng rằng những người khác thấy nó hữu ích:

#include <stddef.h>

namespace std
{
#if defined(__GNUC__)
// Copyright (C) 2008-2020 Free Software Foundation, Inc.
// Copyright (C) 2020 Daniel Rossinsky <danielrossinsky@gmail.com>
//
// This file is part of GCC.
//
// GCC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3, or (at your option)
// any later version.
//
// GCC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

    template<typename T>
    class initializer_list
    {
    public:
        using value_type = T;
        using reference = const T&;
        using const_reference = const T&;
        using size_type = size_t;
        using iterator = const T*;
        using const_iterator = const T*;

    private:
        iterator  m_array;
        size_type m_len;

        // The compiler can call a private constructor.
        constexpr initializer_list(const_iterator itr, size_type st)
            : m_array(itr), m_len(st) { }

    public:
        constexpr initializer_list() noexcept : m_array(0), m_len(0) { }

        // Number of elements.
        constexpr size_type size() const noexcept { return m_len; }

        // First element.
        constexpr const_iterator begin() const noexcept { return m_array; }

        // One past the last element.
        constexpr const_iterator end() const noexcept { return begin() + size(); }
    };
#elif defined(__clang__)
// Copyright (c) 2019 Chandler Carruth <https://github.com/chandlerc>
// Copyright (c) 2018 Louis Dionne <https://github.com/ldionne>
// Copyright (c) 2017 Eric <https://github.com/EricWF>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// ---- LLVM Exceptions to the Apache 2.0 License ----
//
// As an exception, if, as a result of your compiling your source code, portions
// of this Software are embedded into an Object form of such source code, you
// may redistribute such embedded portions in such Object form without complying
// with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
//
// In addition, if you combine or link compiled forms of this Software with
// software that is licensed under the GPLv2 ("Combined Software") and if a
// court of competent jurisdiction determines that the patent provision (Section
// 3), the indemnity provision (Section 9) or other Section of the License
// conflicts with the conditions of the GPLv2, you may retroactively and
// prospectively choose to deem waived or otherwise exclude such Section(s) of
// the License, but only in their entirety and only with respect to the Combined
// Software.

    template<typename T>
    class initializer_list
    {
    private:
        const T* m_first;
        const T* m_last;

    public:
        using value_type      = T;
        using reference       = const T&;
        using const_reference = const T&;
        using size_type       = size_t;
        using iterator        = const T*;
        using const_iterator  = const T*;

        initializer_list() noexcept : m_first(nullptr), m_last(nullptr) {}

        // Number of elements.
        size_t size() const noexcept { return m_last - m_first; }

        // First element.
        const T* begin() const noexcept { return m_first; }

        // One past the last element.
        const T* end() const noexcept { return m_last; }
    };
#elif defined(_MSC_VER)
// Copyright (c) Microsoft Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// ---- LLVM Exceptions to the Apache 2.0 License ----
//
// As an exception, if, as a result of your compiling your source code, portions
// of this Software are embedded into an Object form of such source code, you
// may redistribute such embedded portions in such Object form without complying
// with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
//
// In addition, if you combine or link compiled forms of this Software with
// software that is licensed under the GPLv2 ("Combined Software") and if a
// court of competent jurisdiction determines that the patent provision (Section
// 3), the indemnity provision (Section 9) or other Section of the License
// conflicts with the conditions of the GPLv2, you may retroactively and
// prospectively choose to deem waived or otherwise exclude such Section(s) of
// the License, but only in their entirety and only with respect to the Combined
// Software.

    template<typename T>
    class initializer_list
    {
    public:
        using value_type = T;
        using reference = const T&;
        using const_reference = const T&;
        using size_type = size_t;
        using iterator = const T*;
        using const_iterator = const T*;

        constexpr initializer_list() noexcept : m_first(nullptr), m_last(nullptr) {}

        constexpr initializer_list(const T* first, const T* last) noexcept
            : m_first(first), m_last(last) {}

        // First element.
        constexpr const T* begin() const noexcept { return m_first; }

        // One past the last element.
        constexpr const T* end() const noexcept { return m_last; }

        // Number of elements.
        constexpr size_t size() const noexcept
        {
            return static_cast<size_t>(m_last - m_first);
        }

    private:
        const T* m_first;
        const T* m_last;
    };
#else
    #error "Initializer_list is not supported for this compiler"
#endif

    template<typename T>
    constexpr const T* begin(initializer_list<T> il) noexcept 
    {
        return il.begin();
    }

    template<typename T>
    constexpr const T* end(initializer_list<T> il) noexcept
    {
        return il.end();
    }
}

GHI CHÚ:

Tôi đã thêm thông báo bản quyền với phần mở đầu giấy phép của từng triển khai ngay phía trên triển khai để ghi công cho người có tín dụng đối với mã và thúc đẩy sử dụng hợp pháp.

IANAL:

Bản quyền duy nhất được đưa vào đúng cách là từ gcc, phiên bản msvc thiếu một năm và clang (llvm) nên có bản quyền được chỉ định cho những người đóng góp mà tôi đã làm theo cách thủ công. Tuy nhiên, tôi không phải là chuyên gia và có thể đã bỏ sót / hiểu sai cách tôi được phép chia sẻ mã. Nếu vậy, vui lòng cho tôi biết và tôi sẽ áp dụng các thay đổi ngay lập tức.

Ngoài ra, theo như tôi hiểu thì Apache-2.0 chỉ tương thích với GPLv3 theo một hướng. bạn có thể cấp phép lại toàn bộ mã của tôi theo GPLv3 nhưng không phải trong Apache-2.0

BẰNG CHỨNG LÀM VIỆC:

Ví dụ tôi đã sử dụng để hiển thị bằng chứng phiên bản của tôi hoạt động được lấy từ learningncpp :

  1. Arduino 1.8.9
  2. x86 msvc v19.28
  3. x86-64 tiếng kêu (thân cây)
  4. x86-64 gcc (thân cây)
0 hữu ích 0 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ c++ c++11 initializer-list , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading