123789456ye

已AFO

Proxy 库解析(四)

前言

本来说 Proxy 是个 C++20 的头文件库,结果我本地的 GCC12 又编译不过去,逼得我花了两个多小时把整套工具链都升了一遍
顺手换了个 clangd,This is true LSP! 并非,看起来好像也没比 intelligence 多强,加上编译器还是 GCC 于是又换回去了
回到正题,本文受到这个的启发,我顺了一遍基本上是一样的,只是有些代码的名字或者位置变了
可以结合本文的结果,更好的理解中间发生了什么
其最新的提案,写的很清楚,也建议看一看,理一理思路,提案
但是读完了还是觉得,别的都不错,强制写 12 个 accessor 重载还是太蠢了,用宏来解决就更蠢了

中间结果

让 claude code 写了个输出中间结果和类型的代码如下,试着玩一玩可能会有想不到的发现

点击查看代码
#include "proxy/v4/proxy.h"
#include <iostream>
#include <iomanip>
#include <typeinfo>
#include <type_traits>
#include <string>
#include <sstream>
#include <memory>
#include <cxxabi.h>
#include <concepts>

// Utility to demangle type names
std::string demangle(const char* name) {
    int status;
    char* demangled = abi::__cxa_demangle(name, nullptr, nullptr, &status);
    if (status == 0) {
        std::string result(demangled);
        free(demangled);
        return result;
    }
    return name;
}

// Helper to convert constraint_level enum to string
const char* constraint_level_to_string(pro::constraint_level level) {
    switch (level) {
        case pro::constraint_level::none: return "none";
        case pro::constraint_level::nontrivial: return "nontrivial";
        case pro::constraint_level::nothrow: return "nothrow";
        case pro::constraint_level::trivial: return "trivial";
        default: return "unknown";
    }
}

// Helper to convert bool to string
const char* bool_to_string(bool value) {
    return value ? "true" : "false";
}

// === Trait to strip function qualifiers and record info ===
template<typename T>
struct function_traits_ex {
    using base_type = T;            // fallback, for non-function types
    static constexpr int ref_qual = 0;  // 0=none, 1=&, 2=&&
    static constexpr bool is_noexcept = false;
    static constexpr bool is_const = false;
};

// Plain function
template<typename R, typename... Args>
struct function_traits_ex<R(Args...)> {
    using base_type = R(Args...);  // naked function type
    static constexpr int ref_qual = 0;
    static constexpr bool is_noexcept = false;
    static constexpr bool is_const = false;
};

template<typename R, typename... Args>
struct function_traits_ex<R(Args...) noexcept> {
    using base_type = R(Args...);  // strip noexcept
    static constexpr int ref_qual = 0;
    static constexpr bool is_noexcept = true;
    static constexpr bool is_const = false;
};

// const-qualified
template<typename R, typename... Args>
struct function_traits_ex<R(Args...) const> {
    using base_type = R(Args...);
    static constexpr int ref_qual = 0;
    static constexpr bool is_noexcept = false;
    static constexpr bool is_const = true;
};

template<typename R, typename... Args>
struct function_traits_ex<R(Args...) const noexcept> {
    using base_type = R(Args...);
    static constexpr int ref_qual = 0;
    static constexpr bool is_noexcept = true;
    static constexpr bool is_const = true;
};

// & qualified
template<typename R, typename... Args>
struct function_traits_ex<R(Args...) &> {
    using base_type = R(Args...);
    static constexpr int ref_qual = 1;
    static constexpr bool is_noexcept = false;
    static constexpr bool is_const = false;
};

template<typename R, typename... Args>
struct function_traits_ex<R(Args...) & noexcept> {
    using base_type = R(Args...);
    static constexpr int ref_qual = 1;
    static constexpr bool is_noexcept = true;
    static constexpr bool is_const = false;
};

template<typename R, typename... Args>
struct function_traits_ex<R(Args...) const &> {
    using base_type = R(Args...);
    static constexpr int ref_qual = 1;
    static constexpr bool is_noexcept = false;
    static constexpr bool is_const = true;
};

template<typename R, typename... Args>
struct function_traits_ex<R(Args...) const & noexcept> {
    using base_type = R(Args...);
    static constexpr int ref_qual = 1;
    static constexpr bool is_noexcept = true;
    static constexpr bool is_const = true;
};

// && qualified
template<typename R, typename... Args>
struct function_traits_ex<R(Args...) &&> {
    using base_type = R(Args...);
    static constexpr int ref_qual = 2;
    static constexpr bool is_noexcept = false;
    static constexpr bool is_const = false;
};

template<typename R, typename... Args>
struct function_traits_ex<R(Args...) && noexcept> {
    using base_type = R(Args...);
    static constexpr int ref_qual = 2;
    static constexpr bool is_noexcept = true;
    static constexpr bool is_const = false;
};

template<typename R, typename... Args>
struct function_traits_ex<R(Args...) const &&> {
    using base_type = R(Args...);
    static constexpr int ref_qual = 2;
    static constexpr bool is_noexcept = false;
    static constexpr bool is_const = true;
};

template<typename R, typename... Args>
struct function_traits_ex<R(Args...) const && noexcept> {
    using base_type = R(Args...);
    static constexpr int ref_qual = 2;
    static constexpr bool is_noexcept = true;
    static constexpr bool is_const = true;
};

// === Updated print_type_info ===
template<typename T>
void print_type_info(const std::string& label) {
    using traits = function_traits_ex<T>;
    using Stripped = typename traits::base_type;

    // Always use the stripped base type for typeid
    std::cout << label << ": " << demangle(typeid(Stripped).name());

    // Append qualifiers
    if constexpr (traits::ref_qual == 1) std::cout << " &";
    if constexpr (traits::ref_qual == 2) std::cout << " &&";
    if constexpr (traits::is_noexcept) std::cout << " noexcept";
    if constexpr (traits::is_const) std::cout << " const";

    std::cout << std::endl;

    // Trait checks should not apply to function types directly
    /* if constexpr (std::is_void_v<std::remove_cvref_t<T>>) {
        std::cout << "  Size: N/A (void type)" << std::endl;
        std::cout << "  Alignment: N/A (void type)" << std::endl;
        std::cout << "  Trivially copyable: N/A" << std::endl;
    } else if constexpr (std::is_function_v<Stripped>) {
        std::cout << "  Size: N/A (function type)" << std::endl;
        std::cout << "  Alignment: N/A (function type)" << std::endl;
        std::cout << "  Trivially copyable: N/A" << std::endl;
    } else {
        std::cout << "  Size: " << sizeof(Stripped) << " bytes" << std::endl;
        std::cout << "  Alignment: " << alignof(Stripped) << " bytes" << std::endl;
        std::cout << "  Trivially copyable: "
                  << bool_to_string(std::is_trivially_copyable_v<Stripped>) << std::endl;
        std::cout << "  Trivially destructible: "
                  << bool_to_string(std::is_trivially_destructible_v<Stripped>) << std::endl;
        std::cout << "  Trivially move constructible: "
                  << bool_to_string(std::is_trivially_move_constructible_v<Stripped>) << std::endl;
        std::cout << "  Copy constructible: "
                  << bool_to_string(std::is_copy_constructible_v<Stripped>) << std::endl;
        std::cout << "  Nothrow copy constructible: "
                  << bool_to_string(std::is_nothrow_copy_constructible_v<Stripped>) << std::endl;
        std::cout << "  Nothrow move constructible: "
                  << bool_to_string(std::is_nothrow_move_constructible_v<Stripped>) << std::endl;
    } */
}


// Helper to extract tuple elements
template<typename Tuple, std::size_t... Is>
void print_tuple_elements_impl(std::index_sequence<Is...>, const std::string& prefix) {
    ((print_type_info<std::tuple_element_t<Is, Tuple>>(
        prefix + "[" + std::to_string(Is) + "]")), ...);
}

template<typename Tuple>
void print_tuple_elements(const std::string& label) {
    constexpr auto size = std::tuple_size_v<Tuple>;
    std::cout << label << " (size: " << size << "):" << std::endl;
    if constexpr (size > 0) {
        print_tuple_elements_impl<Tuple>(std::make_index_sequence<size>{}, "  Element");
    }
}

// Facade introspection
template<pro::facade F>
struct facade_inspector {
    using facade_type = F;
    using convention_types = typename F::convention_types;
    using reflection_types = typename F::reflection_types;
    
    static void inspect_facade() {
        std::cout << "\n=== FACADE INSPECTION ===" << std::endl;
        print_type_info<F>("Facade Type");
        
        std::cout << "\nFacade Configuration:" << std::endl;
        std::cout << "  max_size: " << F::max_size << " bytes" << std::endl;
        std::cout << "  max_align: " << F::max_align << " bytes" << std::endl;
        std::cout << "  copyability: " << constraint_level_to_string(F::copyability) << std::endl;
        std::cout << "  relocatability: " << constraint_level_to_string(F::relocatability) << std::endl;
        std::cout << "  destructibility: " << constraint_level_to_string(F::destructibility) << std::endl;
        
        print_tuple_elements<convention_types>("Convention Types");
        print_tuple_elements<reflection_types>("Reflection Types");
    }
};

// Proxy internal structure introspection
template<pro::facade F>
struct proxy_internal_inspector {
private:
    // Access private members through friendship exploitation
    static const auto& get_meta_unsafe(const pro::proxy<F>& p) {
        return pro::details::proxy_helper::get_meta(p);
    }
    
    template<typename P>
    static auto get_ptr_unsafe(const pro::proxy<F>& p) {
        return pro::details::proxy_helper::get_ptr<P, F, pro::details::qualifier_type::const_lv>(p);
    }

public:
    using facade_traits = pro::details::facade_traits<F>;
    using meta_type = typename facade_traits::meta;
    using indirect_accessor = typename facade_traits::indirect_accessor;
    using direct_accessor = typename facade_traits::direct_accessor;
    
    static void inspect_proxy_structure() {
        std::cout << "\n=== PROXY INTERNAL STRUCTURE ===" << std::endl;
        print_type_info<pro::proxy<F>>("Proxy Type");
        print_type_info<meta_type>("Meta Type");
        print_type_info<indirect_accessor>("Indirect Accessor");
        print_type_info<direct_accessor>("Direct Accessor");
        
        // Meta pointer inspection
        using meta_ptr_type = pro::details::meta_ptr<meta_type>;
        print_type_info<meta_ptr_type>("Meta Pointer Type");
        
        std::cout << "\nStorage Details:" << std::endl;
        std::cout << "  Storage size: " << F::max_size << " bytes" << std::endl;
        std::cout << "  Storage alignment: " << F::max_align << " bytes" << std::endl;
        std::cout << "  Actual proxy size: " << sizeof(pro::proxy<F>) << " bytes" << std::endl;
        
        // Check if meta is stored inline or indirectly
        if constexpr (sizeof(meta_type) <= sizeof(pro::details::ptr_prototype) &&
                      alignof(meta_type) <= alignof(pro::details::ptr_prototype) &&
                      std::is_nothrow_default_constructible_v<meta_type> &&
                      std::is_trivially_copyable_v<meta_type>) {
            std::cout << "  Meta storage: INLINE (direct)" << std::endl;
        } else {
            std::cout << "  Meta storage: INDIRECT (pointer)" << std::endl;
        }
    }
    
    template<typename T>
    static void inspect_concrete_instance(const pro::proxy<F>& p) {
        std::cout << "\n=== CONCRETE INSTANCE INSPECTION ===" << std::endl;
        
        if (!p.has_value()) {
            std::cout << "Proxy is empty!" << std::endl;
            return;
        }
        
        print_type_info<T>("Stored Concrete Type");
        
        // Get the meta object
        const auto& meta = get_meta_unsafe(p);
        std::cout << "Meta object address: " << &meta << std::endl;
        
        // Try to access the stored object (this is very unsafe!)
        try {
            const T& stored_obj = get_ptr_unsafe<T>(p);
            std::cout << "Stored object address: " << &stored_obj << std::endl;
            std::cout << "Successfully accessed stored object!" << std::endl;
        } catch (...) {
            std::cout << "Failed to access stored object (type mismatch?)" << std::endl;
        }
    }
    
    // Extract dispatcher information (very advanced)
    template<bool IsDirect, typename D, typename O>
    static void inspect_dispatcher() {
        using invocation_meta = pro::details::invocation_meta<F, IsDirect, D, O>;
        using overload_traits = pro::details::overload_traits<O>;
        
        std::cout << "\n=== DISPATCHER INSPECTION ===" << std::endl;
        std::cout << "Is Direct: " << bool_to_string(IsDirect) << std::endl;
        print_type_info<D>("Dispatch Type");
        print_type_info<O>("Overload Type");
        print_type_info<invocation_meta>("Invocation Meta");
        print_type_info<typename overload_traits::return_type>("Return Type");
        
        std::cout << "Qualifier: ";
        switch (overload_traits::qualifier) {
            case pro::details::qualifier_type::lv: std::cout << "lvalue&"; break;
            case pro::details::qualifier_type::const_lv: std::cout << "const lvalue&"; break;
            case pro::details::qualifier_type::rv: std::cout << "rvalue&&"; break;
            case pro::details::qualifier_type::const_rv: std::cout << "const rvalue&&"; break;
        }
        std::cout << std::endl;
        
        // Additional dispatcher analysis
        using dispatcher_type = typename overload_traits::template dispatcher_type<F>;
        print_type_info<dispatcher_type>("Dispatcher Function Type");
        
        std::cout << "Dispatcher function pointer size: " << sizeof(dispatcher_type) << " bytes" << std::endl;
    }
};

// Enhanced convention introspection with overload analysis
template<typename Conv, pro::facade F>
struct convention_inspector {
    static void inspect() {
        std::cout << "\n=== CONVENTION INSPECTION ===" << std::endl;
        print_type_info<Conv>("Convention Type");
        
        if constexpr (requires { Conv::is_direct; }) {
            std::cout << "  Is Direct: " << bool_to_string(Conv::is_direct) << std::endl;
        }
        
        if constexpr (requires { typename Conv::dispatch_type; }) {
            print_type_info<typename Conv::dispatch_type>("Dispatch Type");
        }
        
        if constexpr (requires { typename Conv::overload_types; }) {
            using overloads = typename Conv::overload_types;
            print_tuple_elements<overloads>("Overload Types");
            
            // Show how many overloads this dispatcher handles
            constexpr auto num_overloads = std::tuple_size_v<overloads>;
            std::cout << "\nThis dispatcher handles " << num_overloads << " overload(s):" << std::endl;
            
            // Analyze each overload individually
            analyze_overloads<overloads>(std::make_index_sequence<num_overloads>{});
        }
    }
    
private:
    template<typename Overloads, std::size_t... Is>
    static void analyze_overloads(std::index_sequence<Is...>) {
        ((analyze_single_overload<std::tuple_element_t<Is, Overloads>>(Is)), ...);
    }
    
    template<typename Overload>
    static void analyze_single_overload(std::size_t index) {
        std::cout << "\n  --- Overload " << index << " Analysis ---" << std::endl;
        
        if constexpr (pro::details::overload_traits<Overload>::applicable) {
            using traits = pro::details::overload_traits<Overload>;
            
            print_type_info<Overload>("    Signature: ");
            print_type_info<typename traits::return_type>("    Return type: ");
            
            std::cout << "    Qualifier: ";
            switch (traits::qualifier) {
                case pro::details::qualifier_type::lv: 
                    std::cout << "lvalue reference (&)"; break;
                case pro::details::qualifier_type::const_lv: 
                    std::cout << "const lvalue reference (const &)"; break;
                case pro::details::qualifier_type::rv: 
                    std::cout << "rvalue reference (&&)"; break;
                case pro::details::qualifier_type::const_rv: 
                    std::cout << "const rvalue reference (const &&)"; break;
            }
            std::cout << std::endl;
            
            // Show dispatcher function type
            using dispatcher_type = typename traits::template dispatcher_type<F>;
            print_type_info<dispatcher_type>("    Dispatcher function type: ");
            std::cout << "    Dispatcher size: " << sizeof(dispatcher_type) << " bytes" << std::endl;
            
        } else {
            std::cout << "    Invalid overload signature!" << std::endl;
        }
    }
};

// Memory layout inspector
template<pro::facade F>
void inspect_memory_layout(const pro::proxy<F>& p) {
    std::cout << "\n=== MEMORY LAYOUT INSPECTION ===" << std::endl;
    
    const unsigned char* proxy_start = reinterpret_cast<const unsigned char*>(&p);
    std::cout << "Proxy object starts at: " << static_cast<const void*>(proxy_start) << std::endl;
    std::cout << "Proxy object size: " << sizeof(p) << " bytes" << std::endl;
    std::cout << "Has value: " << bool_to_string(p.has_value()) << std::endl;
    
    std::cout << "\n--- Raw Memory Dump ---" << std::endl;
    size_t dump_size = sizeof(p);
    
    // Header
    std::cout << "Offset  ";
    for (int i = 0; i < 16; ++i) {
        std::cout << std::hex << std::setfill('0') << std::setw(2) << i << " ";
    }
    std::cout << " ASCII" << std::endl;
    std::cout << std::string(8 + 16*3 + 6, '-') << std::endl;
    
    for (size_t i = 0; i < dump_size; i += 16) {
        // Print offset
        std::cout << std::hex << std::setfill('0') << std::setw(4) << i << ":  ";
        
        // Print hex bytes
        size_t line_end = std::min(i + 16, dump_size);
        for (size_t j = i; j < line_end; ++j) {
            std::cout << std::hex << std::setfill('0') << std::setw(2) 
                      << static_cast<unsigned>(proxy_start[j]) << " ";
        }
        
        // Pad remaining space if less than 16 bytes
        for (size_t j = line_end; j < i + 16; ++j) {
            std::cout << "   ";
        }
        
        // Print ASCII representation
        std::cout << " |";
        for (size_t j = i; j < line_end; ++j) {
            unsigned char byte = proxy_start[j];
            if (byte >= 32 && byte <= 126) {  // Printable ASCII range
                std::cout << static_cast<char>(byte);
            } else {
                std::cout << '.';
            }
        }
        std::cout << "|" << std::endl;
    }
    
    std::cout << std::dec << std::endl;
    
    // Additional structured analysis
    std::cout << "--- Structured Analysis ---" << std::endl;
    
    // Try to identify different sections of the proxy
    if constexpr (sizeof(typename pro::details::facade_traits<F>::meta) <= sizeof(pro::details::ptr_prototype)) {
        std::cout << "Meta storage: INLINE (stored directly in proxy)" << std::endl;
        std::cout << "Meta section (estimated): bytes 0-" << sizeof(pro::details::ptr_prototype)-1 << std::endl;
        std::cout << "Data section (estimated): bytes " << sizeof(pro::details::ptr_prototype) << "-" << sizeof(p)-1 << std::endl;
    } else {
        std::cout << "Meta storage: INDIRECT (pointer to meta)" << std::endl;
        std::cout << "Meta pointer section: bytes 0-" << sizeof(void*)-1 << std::endl;
        std::cout << "Data section: bytes " << sizeof(void*) << "-" << sizeof(p)-1 << std::endl;
    }
    
    if (dump_size > 32) {
        std::cout << "... (showing first 32 bytes only)" << std::endl;
    }
}

// Test setup - Enhanced with multiple overloads
PRO_DEF_MEM_DISPATCH(MemDraw, Draw);
PRO_DEF_MEM_DISPATCH(MemArea, Area);

struct MultiOverloadDrawable : pro::facade_builder
    ::add_convention<MemDraw, void(std::ostream& output)>        // Non-const lvalue
    ::add_convention<MemDraw, void(std::ostream& output) const>  // Const lvalue  
    ::add_convention<MemDraw, void(std::ostream& output) &&>     // Rvalue
    ::add_convention<MemArea, double() noexcept>                 // Different dispatcher
    ::add_convention<MemArea, double() const noexcept>          // Same dispatcher, different const
    ::add_skill<pro::skills::rtti>
    ::support_copy<pro::constraint_level::nontrivial>
    ::build {};

struct Drawable : pro::facade_builder
    ::add_convention<MemDraw, void(std::ostream& output)>
    ::add_convention<MemArea, double() noexcept>
    ::add_skill<pro::skills::rtti>
    ::support_copy<pro::constraint_level::nontrivial>
    ::build {};

class Rectangle {
public:
    Rectangle(double width, double height) : width_(width), height_(height) {}
    Rectangle(const Rectangle&) = default;

    void Draw(std::ostream& out) const {
        out << "{Rectangle: width = " << width_ << ", height = " << height_ << "}";
    }
    double Area() const noexcept { return width_ * height_; }

private:
    double width_;
    double height_;
};

class Circle {
public:
    Circle(double radius) : radius_(radius) {}
    void Draw(std::ostream& out) const {
        out << "{Circle: radius = " << radius_ << "}";
    }
    double Area() const noexcept { return 3.14159 * radius_ * radius_; }

private:
    double radius_;
};

int main() {
    std::cout << "=== SINGLE OVERLOAD FACADE ANALYSIS ===" << std::endl;
    // Inspect the basic facade structure
    facade_inspector<Drawable>::inspect_facade();
    
    // Inspect proxy internal structure
    proxy_internal_inspector<Drawable>::inspect_proxy_structure();
    
    std::cout << "\n=== MULTI-OVERLOAD FACADE ANALYSIS ===" << std::endl;
    // Compare with multi-overload facade
    facade_inspector<MultiOverloadDrawable>::inspect_facade();
    
    // Create some proxy instances
    pro::proxy<Drawable> rect_proxy = pro::make_proxy<Drawable, Rectangle>(3.0, 4.0);
    pro::proxy<MultiOverloadDrawable> multi_rect = pro::make_proxy<MultiOverloadDrawable, Rectangle>(3.0, 4.0);
    
    // Inspect concrete instances
    proxy_internal_inspector<Drawable>::inspect_concrete_instance<Rectangle>(rect_proxy);
    
    // Memory layout inspection
    inspect_memory_layout(rect_proxy);
    inspect_memory_layout(multi_rect);
    
    // Inspect individual conventions for basic facade
    std::cout << "\n=== BASIC FACADE CONVENTIONS ===" << std::endl;
    using first_convention = std::tuple_element_t<0, typename Drawable::convention_types>;
    using second_convention = std::tuple_element_t<1, typename Drawable::convention_types>;
    
    convention_inspector<first_convention, Drawable>::inspect();
    convention_inspector<second_convention, Drawable>::inspect();
    
    // Inspect conventions for multi-overload facade
    std::cout << "\n=== MULTI-OVERLOAD FACADE CONVENTIONS ===" << std::endl;
    using multi_first_conv = std::tuple_element_t<0, typename MultiOverloadDrawable::convention_types>;
    using multi_second_conv = std::tuple_element_t<1, typename MultiOverloadDrawable::convention_types>;
    
    convention_inspector<multi_first_conv, MultiOverloadDrawable>::inspect();
    convention_inspector<multi_second_conv, MultiOverloadDrawable>::inspect();
    
    return 0;
}
输出如下
点击查看代码
=== SINGLE OVERLOAD FACADE ANALYSIS ===

=== FACADE INSPECTION ===
Facade Type: Drawable

Facade Configuration:
  max_size: 16 bytes
  max_align: 8 bytes
  copyability: nontrivial
  relocatability: trivial
  destructibility: nothrow
Convention Types (size: 3):
  Element[0]: pro::v4::details::conv_impl<false, MemDraw, void (std::ostream&)>
  Element[1]: pro::v4::details::conv_impl<false, MemArea, double () noexcept>
  Element[2]: pro::v4::details::conv_impl<false, pro::v4::details::proxy_cast_dispatch, void (pro::v4::details::proxy_cast_context) &, void (pro::v4::details::proxy_cast_context) const &, void (pro::v4::details::proxy_cast_context) &&>
Reflection Types (size: 1):
  Element[0]: pro::v4::details::refl_impl<false, pro::v4::details::proxy_typeid_reflector>

=== PROXY INTERNAL STRUCTURE ===
Proxy Type: pro::v4::proxy<Drawable>
Meta Type: pro::v4::details::composite_meta<pro::v4::details::invocation_meta<Drawable, true, pro::v4::details::copy_dispatch, void (pro::v4::proxy<Drawable>&) const>, pro::v4::details::invocation_meta<Drawable, true, pro::v4::details::destroy_dispatch, void () noexcept>, pro::v4::details::invocation_meta<Drawable, false, MemDraw, void (std::ostream&)>, pro::v4::details::invocation_meta<Drawable, false, MemArea, double () noexcept>, pro::v4::details::invocation_meta<Drawable, false, pro::v4::details::proxy_cast_dispatch, void (pro::v4::details::proxy_cast_context) &>, pro::v4::details::invocation_meta<Drawable, false, pro::v4::details::proxy_cast_dispatch, void (pro::v4::details::proxy_cast_context) const &>, pro::v4::details::invocation_meta<Drawable, false, pro::v4::details::proxy_cast_dispatch, void (pro::v4::details::proxy_cast_context) &&>, pro::v4::details::refl_meta<false, pro::v4::details::proxy_typeid_reflector> >
Indirect Accessor: pro::v4::details::composite_accessor<MemDraw::accessor<pro::v4::proxy_indirect_accessor<Drawable>, MemDraw, void (std::ostream&)>, MemArea::accessor<pro::v4::proxy_indirect_accessor<Drawable>, MemArea, double () noexcept>, pro::v4::details::proxy_cast_dispatch::accessor<pro::v4::proxy_indirect_accessor<Drawable>, pro::v4::details::proxy_cast_dispatch, void (pro::v4::details::proxy_cast_context) &, void (pro::v4::details::proxy_cast_context) const &, void (pro::v4::details::proxy_cast_context) &&>, pro::v4::details::proxy_typeid_reflector::accessor<pro::v4::proxy_indirect_accessor<Drawable>, pro::v4::details::proxy_typeid_reflector> >
Direct Accessor: pro::v4::details::composite_accessor<>
Meta Pointer Type: pro::v4::details::meta_ptr_indirect_impl<pro::v4::details::composite_meta<pro::v4::details::invocation_meta<Drawable, true, pro::v4::details::copy_dispatch, void (pro::v4::proxy<Drawable>&) const>, pro::v4::details::invocation_meta<Drawable, true, pro::v4::details::destroy_dispatch, void () noexcept>, pro::v4::details::invocation_meta<Drawable, false, MemDraw, void (std::ostream&)>, pro::v4::details::invocation_meta<Drawable, false, MemArea, double () noexcept>, pro::v4::details::invocation_meta<Drawable, false, pro::v4::details::proxy_cast_dispatch, void (pro::v4::details::proxy_cast_context) &>, pro::v4::details::invocation_meta<Drawable, false, pro::v4::details::proxy_cast_dispatch, void (pro::v4::details::proxy_cast_context) const &>, pro::v4::details::invocation_meta<Drawable, false, pro::v4::details::proxy_cast_dispatch, void (pro::v4::details::proxy_cast_context) &&>, pro::v4::details::refl_meta<false, pro::v4::details::proxy_typeid_reflector> > >

Storage Details:
  Storage size: 16 bytes
  Storage alignment: 8 bytes
  Actual proxy size: 24 bytes
  Meta storage: INDIRECT (pointer)

=== MULTI-OVERLOAD FACADE ANALYSIS ===

=== FACADE INSPECTION ===
Facade Type: MultiOverloadDrawable

Facade Configuration:
  max_size: 16 bytes
  max_align: 8 bytes
  copyability: nontrivial
  relocatability: trivial
  destructibility: nothrow
Convention Types (size: 3):
  Element[0]: pro::v4::details::conv_impl<false, MemDraw, void (std::ostream&), void (std::ostream&) const, void (std::ostream&) &&>
  Element[1]: pro::v4::details::conv_impl<false, MemArea, double () noexcept, double () noexcept const>
  Element[2]: pro::v4::details::conv_impl<false, pro::v4::details::proxy_cast_dispatch, void (pro::v4::details::proxy_cast_context) &, void (pro::v4::details::proxy_cast_context) const &, void (pro::v4::details::proxy_cast_context) &&>
Reflection Types (size: 1):
  Element[0]: pro::v4::details::refl_impl<false, pro::v4::details::proxy_typeid_reflector>

=== CONCRETE INSTANCE INSPECTION ===
Stored Concrete Type: Rectangle
Meta object address: 0x40e880
Stored object address: 0x7fffffffd3a0
Successfully accessed stored object!

=== MEMORY LAYOUT INSPECTION ===
Proxy object starts at: 0x7fffffffd430
Proxy object size: 24 bytes
Has value: true

--- Raw Memory Dump ---
Offset  00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f  ASCII
--------------------------------------------------------------
0000:  80 e8 40 00 00 00 00 00 00 00 00 00 00 00 08 40  |..@............@|
0010:  00 00 00 00 00 00 10 40                          |.......@|

--- Structured Analysis ---
Meta storage: INDIRECT (pointer to meta)
Meta pointer section: bytes 0-7
Data section: bytes 8-23

=== MEMORY LAYOUT INSPECTION ===
Proxy object starts at: 0x7fffffffd410
Proxy object size: 24 bytes
Has value: true

--- Raw Memory Dump ---
Offset  00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f  ASCII
--------------------------------------------------------------
0000:  c0 e8 40 00 00 00 00 00 00 00 00 00 00 00 08 40  |..@............@|
0010:  00 00 00 00 00 00 10 40                          |.......@|

--- Structured Analysis ---
Meta storage: INDIRECT (pointer to meta)
Meta pointer section: bytes 0-7
Data section: bytes 8-23

=== BASIC FACADE CONVENTIONS ===

=== CONVENTION INSPECTION ===
Convention Type: pro::v4::details::conv_impl<false, MemDraw, void (std::ostream&)>
  Is Direct: false
Dispatch Type: MemDraw
Overload Types (size: 1):
  Element[0]: void (std::ostream&)

This dispatcher handles 1 overload(s):

  --- Overload 0 Analysis ---
    Signature: : void (std::ostream&)
    Return type: : void
    Qualifier: lvalue reference (&)
    Dispatcher function type: : void (*)(pro::v4::proxy<Drawable>&, std::ostream&)
    Dispatcher size: 8 bytes

=== CONVENTION INSPECTION ===
Convention Type: pro::v4::details::conv_impl<false, MemArea, double () noexcept>
  Is Direct: false
Dispatch Type: MemArea
Overload Types (size: 1):
  Element[0]: double () noexcept

This dispatcher handles 1 overload(s):

  --- Overload 0 Analysis ---
    Signature: : double () noexcept
    Return type: : double
    Qualifier: lvalue reference (&)
    Dispatcher function type: : double (*)(pro::v4::proxy<Drawable>&) noexcept
    Dispatcher size: 8 bytes

=== MULTI-OVERLOAD FACADE CONVENTIONS ===

=== CONVENTION INSPECTION ===
Convention Type: pro::v4::details::conv_impl<false, MemDraw, void (std::ostream&), void (std::ostream&) const, void (std::ostream&) &&>
  Is Direct: false
Dispatch Type: MemDraw
Overload Types (size: 3):
  Element[0]: void (std::ostream&)
  Element[1]: void (std::ostream&) const
  Element[2]: void (std::ostream&) &&

This dispatcher handles 3 overload(s):

  --- Overload 0 Analysis ---
    Signature: : void (std::ostream&)
    Return type: : void
    Qualifier: lvalue reference (&)
    Dispatcher function type: : void (*)(pro::v4::proxy<MultiOverloadDrawable>&, std::ostream&)
    Dispatcher size: 8 bytes

  --- Overload 1 Analysis ---
    Signature: : void (std::ostream&) const
    Return type: : void
    Qualifier: const lvalue reference (const &)
    Dispatcher function type: : void (*)(pro::v4::proxy<MultiOverloadDrawable> const&, std::ostream&)
    Dispatcher size: 8 bytes

  --- Overload 2 Analysis ---
    Signature: : void (std::ostream&) &&
    Return type: : void
    Qualifier: rvalue reference (&&)
    Dispatcher function type: : void (*)(pro::v4::proxy<MultiOverloadDrawable>&&, std::ostream&)
    Dispatcher size: 8 bytes

=== CONVENTION INSPECTION ===
Convention Type: pro::v4::details::conv_impl<false, MemArea, double () noexcept, double () noexcept const>
  Is Direct: false
Dispatch Type: MemArea
Overload Types (size: 2):
  Element[0]: double () noexcept
  Element[1]: double () noexcept const

This dispatcher handles 2 overload(s):

  --- Overload 0 Analysis ---
    Signature: : double () noexcept
    Return type: : double
    Qualifier: lvalue reference (&)
    Dispatcher function type: : double (*)(pro::v4::proxy<MultiOverloadDrawable>&) noexcept
    Dispatcher size: 8 bytes

  --- Overload 1 Analysis ---
    Signature: : double () noexcept const
    Return type: : double
    Qualifier: const lvalue reference (const &)
    Dispatcher function type: : double (*)(pro::v4::proxy<MultiOverloadDrawable> const&) noexcept
    Dispatcher size: 8 bytes

facade

以下均以 Drawable 为例,其它的类似
我们 demangle facade 也能得到它的类型 Drawable
首先 convention_types, reflection_types 是在 facade 下面的,内容如下
convention_types 是

tuple<
    conv_impl<false, MemDraw, void (std::ostream&)>,
    conv_impl<false, MemArea, double () noexcept>,
    conv_impl<false, proxy_cast_dispatch, void (proxy_cast_context) &, void (proxy_cast_context) const &, void (proxy_cast_context) &&>
>

reflection_types 是

tuple<
    refl_impl<false, proxy_typeid_reflector>
>

前面两个很好理解,就是在add_convention注册的内容
第三条 convention,以及 reflection,都是注册 rtti 带来的
阅读源码可以发现 skill 有 indirect_rtti(rtti), direct_rtti, slim, as_view, as_weak 这几种,而且都是 add_(in)direct_convention 的 wrapper,不知道为什么要切出来
那么 reflection 是哪来的?
我们可以试着改成别的 skills 比如 as_view,然后发现没有 reflection 了
仔细看,只有 rtti 是调用 add_indirect_convention 的,而别的都是 direct,大概就是这样加入refl_impl<false, R>,后面把refl_impl<true, R>给剔除就行

proxy

它的 meta 类型如下

composite_meta<
    invocation_meta<Drawable, true, copy_dispatch, void (proxy<Drawable>&) const>,
    invocation_meta<Drawable, true, destroy_dispatch, void () noexcept>,
    invocation_meta<Drawable, false, MemDraw, void (std::ostream&)>,
    invocation_meta<Drawable, false, MemArea, double () noexcept>,
    invocation_meta<Drawable, false, proxy_cast_dispatch, void (proxy_cast_context) &>,
    invocation_meta<Drawable, false, proxy_cast_dispatch, void (proxy_cast_context) const &>,
    invocation_meta<Drawable, false, proxy_cast_dispatch, void (proxy_cast_context) &&>,
    refl_meta<false, proxy_typeid_reflector>
>

第一条是support_copy,第二条是默认带的析构,第三四条是我们加的 convention
后面全是 rtti 的,注意 add_indirect_convention 这里是会把写的重载全部加进去
invocation_meta主要的作用是在invoke_impl用来拿到 dispatcher,也就是具体的函数
它的 indirect accessor 类型如下,相当的一目了然

composite_accessor<
    MemDraw::accessor<proxy_indirect_accessor<Drawable>, MemDraw, void (std::ostream&)>,
    MemArea::accessor<proxy_indirect_accessor<Drawable>, MemArea, double () noexcept>,
    proxy_cast_dispatch::accessor<
        proxy_indirect_accessor<Drawable>,
        proxy_cast_dispatch,
        void (proxy_cast_context) &,
        void (proxy_cast_context) const &,
        void (proxy_cast_context) &&
    >,
    proxy_typeid_reflector::accessor<
        proxy_indirect_accessor<Drawable>,
        proxy_typeid_reflector
    >
>

accessor 类型如下,为空

composite_accessor<>

meta pointer 类型如下,其实就是在 meta 外面再包一层

meta_ptr_indirect_impl<
    composite_meta<
        invocation_meta<Drawable, true, copy_dispatch, void (proxy<Drawable>&) const>,
        invocation_meta<Drawable, true, destroy_dispatch, void () noexcept>,
        invocation_meta<Drawable, false, MemDraw, void (std::ostream&)>,
        invocation_meta<Drawable, false, MemArea, double () noexcept>,
        invocation_meta<Drawable, false, proxy_cast_dispatch, void (proxy_cast_context) &>,
        invocation_meta<Drawable, false, proxy_cast_dispatch, void (proxy_cast_context) const &>,
        invocation_meta<Drawable, false, proxy_cast_dispatch, void (proxy_cast_context) &&>,
        refl_meta<false, proxy_typeid_reflector>
    >
>

detail

我们取第一个 convention
它的 dispatch_type 是 MemDraw,没什么好说的
它的 overload_typesvoid (std::ostream&),注意这里是 types
如果换成 rtti 那条 convention,我们理论上可以得到void (proxy_cast_context) &, void (proxy_cast_context) const &, void (proxy_cast_context) &&这样的东西,不过需要改下代码
然后我们取第一个 dispatcher,不过这个相当简单,基本是就是看一下 parse 出了什么

Performance

Proxy 首先当然是非侵入的组合来达到多态,这一点从上面的样例就能看出来
但是都写 C++ 了,性能还是得看的吧
虽然说虚函数开销大,但是在现代编译器和CPU的加持下其实也就10-20个周期,看上去开销也不大
总之作者声称这个开销全方位的优于虚函数,包括反编译代码也是,不过也有一些评论指出实际的性能似乎并没有那么好

posted @ 2025-09-21 16:19  123789456ye  阅读(4)  评论(0)    收藏  举报