试图理解委托人,此代码无法编译c ++ 11

时间:2019-06-06 20:44:07

标签: c++

我正在观看此视频https://www.youtube.com/watch?v=QMb4RRFrY-o 并尝试按照示例操作,但我无法编译代码。

他应该从下面的链接复制并粘贴代码,但是我也无法对其进行编译。

我正在使用QT来编译启用了Visual Studio 2015 x64和c ++ 11的计算机。

https://codereview.stackexchange.com/questions/14730/impossibly-fast-delegate-in-c11

示例1

#include <iostream>
#include <functional>

#include "delegate.hpp"

void fn1(){
 std::cout << "Function one! \n";
}

void fn2(){
 std::cout << "Function two! \n";
}

int main()
{
    std::function<decltype (fn1)> func;
       delegate<decltype (fn1)> delg;

       func = delg = fn1;

       func();
       delg();

       func = delg = fn2;

       func();
       delg();

 }

下面的代码是proxy.hpp文件。

// This file is a part of the IncludeOS unikernel - www.includeos.org
    //
    // Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
    // and Alfred Bratterud
    //
    // 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.

    #ifndef DELEGATE_HPP_INCLUDED
    #define DELEGATE_HPP_INCLUDED

    #include <type_traits>
    #include <functional>
    #include <memory>
    #include <cstddef>

    // ----- SYNOPSIS -----

    namespace spec
    {
        template<size_t, size_t, typename, typename...> class pure;
        template<size_t, size_t, typename, typename...> class inplace_triv;
        template<size_t, size_t, typename, typename...> class inplace;
    }

    namespace detail
    {
        constexpr size_t default_capacity = sizeof(size_t) * 4;

        template<typename T> using default_alignment = std::alignment_of<
            std::function<T>
        >;
    }


    template<
        typename T,
        template<size_t, size_t, typename, typename...> class Spec = spec::inplace,
        size_t size = detail::default_capacity,
        size_t align = detail::default_alignment<T>::value
    >
    class delegate; // unspecified

    template<
        typename R, typename... Args,
        template<size_t, size_t, typename, typename...> class Spec,
        size_t size,
        size_t align
    >
    class delegate<R(Args...), Spec, size, align>;

    class empty_delegate_error : public std::bad_function_call
    {
    public:
        const char* what() const throw() {
          return "Empty delegate called";
        }
    };

    // ----- IMPLEMENTATION -----

    namespace detail
    {
    template<typename R, typename... Args> static R empty_pure(Args...)
    {
        throw empty_delegate_error();
    }

    template<
        typename R,
        typename S,
        typename... Args
    > static R empty_inplace(S&, Args&&... args)
    {
        return empty_pure<R, Args...>(std::forward<Args>(args)...);
    }

    template<
        typename T,
        typename R,
        typename... Args
    > using closure_decay = std::conditional<
        std::is_convertible<T, R(*)(Args...)>::value,
        R(*)(Args...),
        typename std::decay<T>::type
    >;

    template<typename T = void, typename...> struct pack_first
    {
        using type = std::remove_cv_t<T>;
    };

    template<typename... Ts>
    using pack_first_t = typename pack_first<Ts...>::type;

    }

    namespace spec
    {

    // --- pure ---
    template<size_t, size_t, typename R, typename... Args> class pure
    {
    public:
        using invoke_ptr_t = R(*)(Args...);

        explicit pure() noexcept :
            invoke_ptr_{ detail::empty_pure<R, Args...> }
        {}

        template<typename T> explicit pure(T&& func_ptr) noexcept :
            invoke_ptr_{ func_ptr }
        {
            static_assert(std::is_convertible<T, invoke_ptr_t>::value,
                "object not convertible to pure function pointer!");
        }

        pure(const pure&) noexcept = default;
        pure(pure&&) noexcept = default;

        pure& operator= (const pure&) noexcept = default;
        pure& operator= (pure&&) noexcept = default;

        ~pure() = default;

        R operator() (Args&&... args) const
        {
            return invoke_ptr_(std::forward<Args>(args)...);
        }

        bool empty() const noexcept
        {
            return invoke_ptr_ == static_cast<invoke_ptr_t>(
                detail::empty_pure<R, Args...>);
        }

        template<typename T> T* target() const noexcept
        {
            return static_cast<T*>(invoke_ptr_);
        }

    private:
        invoke_ptr_t invoke_ptr_;
    };

    // --- inplace_triv ---
    template<
        size_t size,
        size_t align,
        typename R,
        typename... Args
    > class inplace_triv
    {
    public:
        using storage_t = std::aligned_storage_t<size, align>;
        using invoke_ptr_t = R(*)(storage_t&, Args&&...);

        explicit inplace_triv() noexcept :
            invoke_ptr_{ detail::empty_inplace<R, storage_t, Args...> }
        {
            new(&storage_)std::nullptr_t{ nullptr };
        }

        template<
            typename T,
            typename C = typename detail::closure_decay<T, R, Args...>::type
        > explicit inplace_triv(T&& closure) :
            invoke_ptr_{ static_cast<invoke_ptr_t>(
                [](storage_t& storage, Args&&... args) -> R
                { return reinterpret_cast<C&>(storage)(std::forward<Args>(args)...); }
            )}
        {
            static_assert(sizeof(C) <= size,
                "inplace_triv delegate closure too large!");

            static_assert(std::alignment_of<C>::value <= align,
                "inplace_triv delegate closure alignment too large");

            static_assert(std::is_trivially_copyable<C>::value,
                "inplace_triv delegate closure not trivially copyable!");

            static_assert(std::is_trivially_destructible<C>::value,
                "inplace_triv delegate closure not trivially destructible!");

            new(&storage_)C{ std::forward<T>(closure) };
        }

        inplace_triv(const inplace_triv&) noexcept = default;
        inplace_triv(inplace_triv&&) noexcept = default;

        inplace_triv& operator= (const inplace_triv&) noexcept = default;
        inplace_triv& operator= (inplace_triv&&) noexcept = default;

        ~inplace_triv() = default;

        R operator() (Args&&... args) const
        {
            return invoke_ptr_(storage_, std::forward<Args>(args)...);
        }

        bool empty() const noexcept
        {
            return reinterpret_cast<std::nullptr_t&>(storage_) == nullptr;
        }

        template<typename T> T* target() const noexcept
        {
            return reinterpret_cast<T*>(&storage_);
        }

    private:
        invoke_ptr_t invoke_ptr_;
        mutable storage_t storage_;
    };

    // --- inplace ---
    template<
        size_t size,
        size_t align,
        typename R,
        typename... Args
    > class inplace
    {
    public:
        using storage_t = std::aligned_storage_t<size, align>;

        using invoke_ptr_t = R(*)(storage_t&, Args&&...);
        using copy_ptr_t = void(*)(storage_t&, storage_t&);
        using destructor_ptr_t = void(*)(storage_t&);

        explicit inplace() noexcept :
            invoke_ptr_{ detail::empty_inplace<R, storage_t, Args...> },
            copy_ptr_{ copy_op<std::nullptr_t, storage_t>() },
            destructor_ptr_{ nullptr }
        {}

        template<
            typename T,
            typename C = typename detail::closure_decay<T, R, Args...>::type
        > explicit inplace(T&& closure) noexcept :
            invoke_ptr_{ static_cast<invoke_ptr_t>(
                [](storage_t& storage, Args&&... args) -> R
                { return reinterpret_cast<C&>(storage)(std::forward<Args>(args)...); }
            ) },
            copy_ptr_{ copy_op<C, storage_t>() },
            destructor_ptr_{ static_cast<destructor_ptr_t>(
                [](storage_t& storage) noexcept -> void
                { reinterpret_cast<C&>(storage).~C(); }
            ) }
        {
            static_assert(sizeof(C) <= size,
                "inplace delegate closure too large");

            static_assert(std::alignment_of<C>::value <= align,
                "inplace delegate closure alignment too large");

            new(&storage_)C{ std::forward<T>(closure) };
        }

        inplace(const inplace& other) :
            invoke_ptr_{ other.invoke_ptr_ },
            copy_ptr_{ other.copy_ptr_ },
            destructor_ptr_{ other.destructor_ptr_ }
        {
            copy_ptr_(storage_, other.storage_);
        }

        inplace(inplace&& other)  :
            storage_ { std::move(other.storage_) },
            invoke_ptr_{ other.invoke_ptr_ },
            copy_ptr_{ other.copy_ptr_ },
            destructor_ptr_{ other.destructor_ptr_ }
        {
            other.destructor_ptr_ = nullptr;
        }

        inplace& operator= (const inplace& other)
        {
            if (this != std::addressof(other))
            {
                invoke_ptr_ = other.invoke_ptr_;
                copy_ptr_ = other.copy_ptr_;

                if (destructor_ptr_)
                    destructor_ptr_(storage_);

                copy_ptr_(storage_, other.storage_);
                destructor_ptr_ = other.destructor_ptr_;
            }
            return *this;
        }

        inplace& operator= (inplace&& other)
        {
            if (this != std::addressof(other))
            {
                if (destructor_ptr_)
                    destructor_ptr_(storage_);

                storage_ = std::move(other.storage_);

                invoke_ptr_ = other.invoke_ptr_;
                copy_ptr_ = other.copy_ptr_;
                destructor_ptr_ = other.destructor_ptr_;

                other.destructor_ptr_ = nullptr;
            }
            return *this;
        }

        ~inplace()
        {
            if (destructor_ptr_)
                destructor_ptr_(storage_);
        }

        R operator() (Args&&... args) const
        {
            return invoke_ptr_(storage_, std::forward<Args>(args)...);
        }

        bool empty() const noexcept
        {
            return destructor_ptr_ == nullptr;
        }

        template<typename T> T* target() const noexcept
        {
            return reinterpret_cast<T*>(&storage_);
        }

    private:
        mutable storage_t storage_ {};

        invoke_ptr_t invoke_ptr_;
        copy_ptr_t copy_ptr_;
        destructor_ptr_t destructor_ptr_;

        template<
            typename T,
            typename S,
            typename std::enable_if_t<
            std::is_copy_constructible<T>::value, int
            > = 0
        > copy_ptr_t copy_op()
        {
            return [](S& dst, S& src) noexcept -> void
            {
                new(&dst)T{ reinterpret_cast<T&>(src) };
            };
        }

        template<
            typename T,
            typename S,
            typename std::enable_if_t<
            !std::is_copy_constructible<T>::value, int
            > = 0
        > copy_ptr_t copy_op()
        {
            static_assert(std::is_copy_constructible<T>::value,
                "constructing delegate with move only type is invalid!");
        }
    };
    } // namespace spec

    template<
        typename R, typename... Args,
        template<size_t, size_t, typename, typename...> class Spec,
        size_t size,
        size_t align
    >
    class delegate<R(Args...), Spec, size, align>
    {
    public:
        using result_type = R;

        using storage_t = Spec<size, align, R, Args...>;

        explicit delegate() noexcept :
            storage_{}
        {}

        template<
            typename T,
            typename = std::enable_if_t<
            !std::is_same<std::decay_t<T>, delegate>::value>
            /*&& std::is_same<
                decltype(std::declval<T&>()(std::declval<Args>()...)),
                R
            >::value>*/
        >
        delegate(T&& val) :
            storage_{ std::forward<T>(val) }
        {}

        // delegating constructors
        delegate(std::nullptr_t) noexcept :
            delegate()
        {}

        // construct with member function pointer

        // object pointer capture
        template<typename C>
        delegate(C* const object_ptr, R(C::* const method_ptr)(Args...))
            noexcept : delegate(
                [object_ptr, method_ptr](Args&&... args) -> R
        {
            return (object_ptr->*method_ptr)(std::forward<Args>(args)...);
        })
        {}

        template<typename C>
        delegate(C* const object_ptr, R(C::* const method_ptr)(Args...) const)
            noexcept : delegate(
                [object_ptr, method_ptr](Args&&... args) -> R
        {
            return (object_ptr->*method_ptr)(std::forward<Args>(args)...);
        })
        {}

        // object reference capture
        template<typename C>
        delegate(C& object_ref, R(C::* const method_ptr)(Args...))
            noexcept : delegate(
                [&object_ref, method_ptr](Args&&... args) -> R
        {
            return (object_ref.*method_ptr)(std::forward<Args>(args)...);
        })
        {}

        template<typename C>
        delegate(C& object_ref, R(C::* const method_ptr)(Args...) const)
            noexcept : delegate(
                [&object_ref, method_ptr](Args&&... args) -> R
        {
            return (object_ref.*method_ptr)(std::forward<Args>(args)...);
        })
        {}

        // object pointer as parameter
        template<
            typename C,
            typename... MemArgs,
            typename std::enable_if_t<
            std::is_same<detail::pack_first_t<Args...>, C*>::value, int> = 0
        > delegate(R(C::* const method_ptr)(MemArgs...))
            noexcept : delegate(
                [method_ptr](C* object_ptr, MemArgs... args) -> R
        {
            return (object_ptr->*method_ptr)(std::forward<MemArgs>(args)...);
        })
        {}

        template<
            typename C,
            typename... MemArgs,
            typename std::enable_if_t<
            std::is_same<detail::pack_first_t<Args...>, C*>::value, int> = 0
        > delegate(R(C::* const method_ptr)(MemArgs...) const)
            noexcept : delegate(
                [method_ptr](C* object_ptr, MemArgs... args) -> R
        {
            return (object_ptr->*method_ptr)(std::forward<MemArgs>(args)...);
        })
        {}

        // object reference as parameter
        template<
            typename C,
            typename... MemArgs,
            typename std::enable_if_t<
            std::is_same<detail::pack_first_t<Args...>, C&>::value, int> = 0
        > delegate(R(C::* const method_ptr)(MemArgs...))
            noexcept : delegate(
                [method_ptr](C& object, MemArgs... args) -> R
        {
            return (object.*method_ptr)(std::forward<MemArgs>(args)...);
        })
        {}

        template<
            typename C,
            typename... MemArgs,
            typename std::enable_if_t<
            std::is_same<detail::pack_first_t<Args...>, C&>::value, int> = 0
        > delegate(R(C::* const method_ptr)(MemArgs...) const)
            noexcept : delegate(
                [method_ptr](C& object, MemArgs... args) -> R
        {
            return (object.*method_ptr)(std::forward<MemArgs>(args)...);
        })
        {}

        // object copy as parameter
        template<
            typename C,
            typename... MemArgs,
            typename std::enable_if_t<
            std::is_same<detail::pack_first_t<Args...>, C>::value, int> = 0
        > delegate(R(C::* const method_ptr)(MemArgs...))
            noexcept : delegate(
                [method_ptr](C object, MemArgs... args) -> R
        {
            return (object.*method_ptr)(std::forward<MemArgs>(args)...);
        })
        {}

        template<
            typename C,
            typename... MemArgs,
            typename std::enable_if_t<
            std::is_same<detail::pack_first_t<Args...>, C>::value, int> = 0
        > delegate(R(C::* const method_ptr)(MemArgs...) const)
            noexcept : delegate(
                [method_ptr](C object, MemArgs... args) -> R
        {
            return (object.*method_ptr)(std::forward<MemArgs>(args)...);
        })
        {}

        delegate(const delegate&) = default;
        delegate(delegate&&) = default;

        delegate& operator= (const delegate&) = default;
        delegate& operator= (delegate&&) = default;

        ~delegate() = default;

        R operator() (Args... args) const
        {
            return storage_(std::forward<Args>(args)...);
        }

        bool operator== (std::nullptr_t) const noexcept
        {
            return storage_.empty();
        }

        bool operator!= (std::nullptr_t) const noexcept
        {
            return !storage_.empty();
        }

        explicit operator bool() const noexcept
        {
            return !storage_.empty();
        }

        void swap(delegate& other)
        {
            storage_t tmp = storage_;
            storage_ = other.storage_;
            other.storage_ = tmp;
        }

        void reset()
        {
            storage_t empty;
            storage_ = empty;
        }

        template<typename T> T* target() const noexcept
        {
            return storage_.template target<T>();
        }

        template<
            typename T,
            typename D = std::shared_ptr<T>,
            typename std::enable_if_t<size >= sizeof(D), int> = 0
        > static delegate make_packed(T&& closure)
        {
            D ptr = std::make_shared<T>(std::forward<T>(closure));
            return [ptr](Args&&... args) -> R
            {
                return (*ptr)(std::forward<Args>(args)...);
            };
        }

        template<
            typename T,
            typename D = std::shared_ptr<T>,
            typename std::enable_if_t<!(size >= sizeof(D)), int> = 0
        > static delegate make_packed(T&&)
        {
            static_assert(size >= sizeof(D), "Cannot pack into delegate");
        }

    private:
        storage_t storage_;
    };

    #endif // DELEGATE_HPP_INCLUDED

错误消息对我来说是个谜,这意味着什么? 如果有人能够解释他们的意思,将不胜感激。

 404: see reference to function template instantiation 'spec::inplace<32,8,R>::inplace<void(__cdecl &)(void),void(__cdecl *)(void)>(T) noexcept' being compiled
        with
        [
            R=void,
            T=void (__cdecl &)(void)
        ]

        C2061: syntax error: identifier 'C' at line 253
        C2061: syntax error: identifier 'C' at line 259
        invalid operands to binary expression ('std::nullptr_t'(aka 'nullptr_t') and 'nullptr_t') at line 212

1 个答案:

答案 0 :(得分:1)

您正在使用C ++ 11进行编译,但是所使用的代码需要C ++ 14。使用C ++ 11进行编译时会遇到很多错误,但是当我使用C ++ 14时它们就会消失。

See here for an explanation of how to compile with C++14 in visual studio!

为什么代码不能用C ++ 11编译? 文件“ delegates.hpp”使用了C ++ 14标准库中的很多东西,而C ++ 11中没有这些东西。

例如,在delegates.hpp的第76行,我们看到

// C++14 (what's found in the file)
using type = std::remove_cv_t<T>; 

在C ++ 11中,这将是

// C++11 version
using type = typename std::remove_cv<T>::type;

要使它在C ++ 11中工作,您需要更改很多代码,因此我建议仅使用C ++ 14。