diff options
33 files changed, 599 insertions, 374 deletions
diff --git a/src/Makefile_Eina_Cxx.am b/src/Makefile_Eina_Cxx.am index 5c5e2dbb75..77cf577fb0 100644 --- a/src/Makefile_Eina_Cxx.am +++ b/src/Makefile_Eina_Cxx.am @@ -12,7 +12,7 @@ bindings/eina_cxx/eina_accessor.hh \ bindings/eina_cxx/eina_array.hh \ bindings/eina_cxx/eina_clone_allocators.hh \ bindings/eina_cxx/eina_error.hh \ -bindings/eina_cxx/eina_eo_base_fwd.hh \ +bindings/eina_cxx/eina_eo_concrete_fwd.hh \ bindings/eina_cxx/eina_fold.hh \ bindings/eina_cxx/eina_inarray.hh \ bindings/eina_cxx/eina_inlist.hh \ diff --git a/src/Makefile_Eo_Cxx.am b/src/Makefile_Eo_Cxx.am index 21987b588d..81c8826579 100644 --- a/src/Makefile_Eo_Cxx.am +++ b/src/Makefile_Eo_Cxx.am @@ -1,4 +1,15 @@ +### Generated Headers + +generated_eo_cxx_bindings = \ +lib/eo/eo_base.eo.hh \ +lib/eo/eo_abstract_class.eo.hh + +CLEANFILES += $(generated_eo_cxx_bindings) + +installed_eocxxheadersdir = $(includedir)/eo-cxx-@VMAJ@ +nodist_installed_eocxxheaders_DATA = $(generated_eo_cxx_bindings) + ### Library if HAVE_CXX11 @@ -9,7 +20,7 @@ bindings/eo_cxx/Eo.hh installed_eocxxheadersdir = $(includedir)/eo-cxx-@VMAJ@/ dist_installed_eocxxheaders_DATA = \ -bindings/eo_cxx/eo_base.hh \ +bindings/eo_cxx/eo_concrete.hh \ bindings/eo_cxx/eo_event.hh \ bindings/eo_cxx/eo_init.hh \ bindings/eo_cxx/eo_wref.hh \ diff --git a/src/Makefile_Eolian_Cxx.am b/src/Makefile_Eolian_Cxx.am index 14cf493d73..ebedc3dfd6 100644 --- a/src/Makefile_Eolian_Cxx.am +++ b/src/Makefile_Eolian_Cxx.am @@ -18,6 +18,7 @@ lib/eolian_cxx/grammar/comment.hh \ lib/eolian_cxx/grammar/eo_class_constructors_generator.hh \ lib/eolian_cxx/grammar/eo_class_events_generator.hh \ lib/eolian_cxx/grammar/eo_class_functions_generator.hh \ +lib/eolian_cxx/grammar/namespace_generator.hh \ lib/eolian_cxx/grammar/eo_class_generator.hh \ lib/eolian_cxx/grammar/eo_header_generator.hh \ lib/eolian_cxx/grammar/inheritance_base_generator.hh \ diff --git a/src/bin/eolian_cxx/convert.cc b/src/bin/eolian_cxx/convert.cc index acb2c78a1e..8f5cec8927 100644 --- a/src/bin/eolian_cxx/convert.cc +++ b/src/bin/eolian_cxx/convert.cc @@ -22,6 +22,34 @@ namespace eolian_cxx { extern efl::eina::log_domain domain; +void +remove_repeated_base(const char* klass_name, efl::eolian::parents_container_type& cont) +{ + Eolian_Class const* klass = ::eolian_class_get_by_name(klass_name); + if (!klass) + { + std::cerr << "Error: could not get eolian class name `" << klass_name << "'" << std::endl; + return; + } + + Eina_Iterator* inheritances = ::eolian_class_inherits_get(klass); + void* curr = 0; + + EINA_ITERATOR_FOREACH(inheritances, curr) + { + if (!curr) + continue; + + const char* parent = static_cast<const char*>(curr); + cont.erase( + std::remove(cont.begin(), cont.end(), safe_lower(class_format_cxx(parent))) + , cont.end()); + + remove_repeated_base(parent, cont); + } + eina_iterator_free(inheritances); +} + static efl::eolian::parameters_container_type _convert_eolian_parameters(Eina_Iterator *parameters, Eolian_Function_Type func_type) @@ -148,13 +176,6 @@ _convert_property_get_to_function(Eolian_Class const& klass, return get_; } -static std::string -_convert_class_name(std::string const& name) -{ - return (name == "eo_base" || name == "eo::base" || name == "") - ? "efl::eo::base" - : name; -} void convert_eolian_inheritances(efl::eolian::eo_class& cls, Eolian_Class const& klass) @@ -163,23 +184,21 @@ convert_eolian_inheritances(efl::eolian::eo_class& cls, Eolian_Class const& klas ::eolian_class_inherits_get(&klass); void *curr; - if (!eina_iterator_next(inheritances, &curr) || !curr) + EINA_ITERATOR_FOREACH(inheritances, curr) { - cls.parent = "efl::eo::base"; - eina_iterator_free(inheritances); - return; + std::string parent = safe_lower(static_cast<const char*>(curr)); + cls.parents.push_back(class_format_cxx(parent)); } - else + eina_iterator_free(inheritances); + + if (cls.parents.empty()) + return; + + inheritances = ::eolian_class_inherits_get(&klass); + EINA_ITERATOR_FOREACH(inheritances, curr) { - // First element is the parent - const char *ptr = static_cast<const char*>(curr); - cls.parent = _convert_class_name(class_format_cxx(safe_lower(ptr))); - - EINA_ITERATOR_FOREACH(inheritances, curr) - { - std::string extension = safe_lower(static_cast<const char*>(curr)); - cls.extensions.push_back(_convert_class_name(class_format_cxx(extension))); - } + if (curr) + remove_repeated_base(static_cast<const char*>(curr), cls.parents); } eina_iterator_free(inheritances); } @@ -213,6 +232,9 @@ convert_eolian_functions(efl::eolian::eo_class& cls, Eolian_Class const& klass) Eolian_Function const& func = *first; Eolian_Function_Type const func_type = function_op_type(func); + if (!function_is_visible(func, func_type)) + continue; + if (function_is_constructor(klass, func)) { cls.constructors.push_back({ @@ -221,7 +243,7 @@ convert_eolian_functions(efl::eolian::eo_class& cls, Eolian_Class const& klass) convert_comments_function(klass, func) }); } - else if (function_is_visible(func, func_type)) + else { cls.functions.push_back({ function_type(func), @@ -239,6 +261,9 @@ convert_eolian_functions(efl::eolian::eo_class& cls, Eolian_Class const& klass) Eolian_Function const& func = *first; Eolian_Function_Type t = ::eolian_function_type_get(&func); + if (!function_is_visible(func, t)) + continue; + if(t == EOLIAN_PROP_GET) { cls.functions.push_back diff --git a/src/bin/eolian_cxx/eolian_cxx.cc b/src/bin/eolian_cxx/eolian_cxx.cc index 5aa477edf0..93e9e442ab 100644 --- a/src/bin/eolian_cxx/eolian_cxx.cc +++ b/src/bin/eolian_cxx/eolian_cxx.cc @@ -101,14 +101,7 @@ generator_options(const Eolian_Class& klass) std::string eo_parent_file = class_base_file(*ext); if (!eo_parent_file.empty()) { - // we have our own eo_base.hh - std::string eo_base_eo = "eo_base.eo"; - if (eo_parent_file.length() < eo_base_eo.length() || - !std::equal(eo_base_eo.begin(), eo_base_eo.end(), - eo_parent_file.end() - eo_base_eo.length())) - { - gen_opts.cxx_headers.push_back(eo_parent_file + ".hh"); - } + gen_opts.cxx_headers.push_back(eo_parent_file + ".hh"); } else { diff --git a/src/bin/eolian_cxx/eolian_wrappers.hh b/src/bin/eolian_cxx/eolian_wrappers.hh index d56379393f..6b0211e798 100644 --- a/src/bin/eolian_cxx/eolian_wrappers.hh +++ b/src/bin/eolian_cxx/eolian_wrappers.hh @@ -350,14 +350,14 @@ parameter_type(Eolian_Function_Parameter const& parameter, { if (type.front().native == "char *") type = { efl::eolian::type_to_native(type) }; - type.front().is_out = true; + type.is_out = true; type.front().native += "*"; } if (parameter_is_const(parameter, func_type)) { - type[0].native.insert(0, "const "); - if (!type[0].binding.empty()) - type[0].binding.insert(0, "const "); + type.front().native.insert(0, "const "); + if (!type.front().binding.empty()) + type.front().binding.insert(0, "const "); } return type; } diff --git a/src/bin/eolian_cxx/type_lookup.hh b/src/bin/eolian_cxx/type_lookup.hh index 1b64bbb20b..f7be16e857 100644 --- a/src/bin/eolian_cxx/type_lookup.hh +++ b/src/bin/eolian_cxx/type_lookup.hh @@ -77,14 +77,14 @@ type_lookup(const Eolian_Type* type, efl::eolian::eolian_type_instance v(types.size()); for (std::size_t i = 0; i != types.size(); ++i) { - v[i] = type_find(lut.begin(), lut.end(), type_from_eolian(*types[i])); + v.parts[i] = type_find(lut.begin(), lut.end(), type_from_eolian(*types[i])); } // Let's degrade to opaque classes when not enough information // is available for complex types - if(v.size() == 1 && type_is_complex(v[0])) + if(v.parts.size() == 1 && type_is_complex(v.front())) { - efl::eolian::eolian_type tmp = v[0]; + efl::eolian::eolian_type tmp = v.front(); return {efl::eolian::type_to_native(tmp)}; } diff --git a/src/bin/eolian_cxx/type_lookup_table.cc b/src/bin/eolian_cxx/type_lookup_table.cc index d4e7c1e9d6..7fa085e9ba 100644 --- a/src/bin/eolian_cxx/type_lookup_table.cc +++ b/src/bin/eolian_cxx/type_lookup_table.cc @@ -13,25 +13,25 @@ type_lookup_table {"Ecore_Task_Cb", eolian_type::callback_, {"Ecore.h"}}, {"Ecore_Timeline_Cb", eolian_type::callback_, {"Ecore.h"}}, {"Edje_Signal_Cb", eolian_type::callback_, {"Edje.h"}}, - {"Eina_Accessor *", eolian_type::complex_, false, false, "efl::eina::accessor", {"eina-cxx/eina_accessor.hh"}}, - {"Eina_Bool", eolian_type::simple_, false, false, "bool", {}}, - {"Eina_Bool *", eolian_type::simple_, false, false, "bool*", {}}, - {"Eina_Inlist *", eolian_type::complex_, false, false, "efl::eina::range_inlist", {"eina-cxx/eina_inlist.hh"}}, - {"Eina_Inlist *", eolian_type::complex_, false, true, "efl::eina::inlist", {"eina-cxx/eina_inlist.hh"}}, - {"Eina_Iterator *", eolian_type::complex_, false, false, "efl::eina::iterator", {"eina-cxx/eina_iterator.hh"}}, - {"Eina_List *", eolian_type::complex_, false, false, "efl::eina::range_list", {"eina-cxx/eina_list.hh"}}, - {"Eina_List *", eolian_type::complex_, false, true, "efl::eina::list", {"eina-cxx/eina_list.hh"}}, - {"const Eina_List *", eolian_type::complex_, true, false, "efl::eina::crange_list", {"eina-cxx/eina_list.hh"}}, + {"Eina_Accessor *", eolian_type::complex_, false, false, true, "::efl::eina::accessor", {"eina-cxx/eina_accessor.hh"}}, + {"Eina_Bool", eolian_type::simple_, false, false, false, "bool", {}}, + {"Eina_Bool *", eolian_type::simple_, false, false, false, "bool*", {}}, + {"Eina_Inlist *", eolian_type::complex_, false, false, true, "::efl::eina::range_inlist", {"eina-cxx/eina_inlist.hh"}}, + {"Eina_Inlist *", eolian_type::complex_, false, true, true, "::efl::eina::inlist", {"eina-cxx/eina_inlist.hh"}}, + {"Eina_Iterator *", eolian_type::complex_, false, false, true, "::efl::eina::iterator", {"eina-cxx/eina_iterator.hh"}}, + {"Eina_List *", eolian_type::complex_, false, false, true, "::efl::eina::range_list", {"eina-cxx/eina_list.hh"}}, + {"Eina_List *", eolian_type::complex_, false, true, true, "::efl::eina::list", {"eina-cxx/eina_list.hh"}}, + {"const Eina_List *", eolian_type::complex_, true, false, true, "::efl::eina::crange_list", {"eina-cxx/eina_list.hh"}}, {"Eio_Filter_Direct_Cb", eolian_type::callback_, {"Eio.h"}}, - {"Emodel *", eolian_type::simple_, false, false, "emodel", {"Emodel.hh"}}, - {"Eo *", eolian_type::simple_, false, true, "efl::eo::base", {"eo_base.hh"}}, - {"Eo *", eolian_type::simple_, false, false, "efl::eo::base", {"eo_base.hh"}}, + {"Emodel *", eolian_type::simple_, false, false, true, "::emodel", {"Emodel.hh"}}, + {"Eo *", eolian_type::simple_, false, true, true, "::efl::eo::concrete", {"eo_concrete.hh"}}, + {"Eo *", eolian_type::simple_, false, false, true, "::efl::eo::concrete", {"eo_concrete.hh"}}, //{"Evas_Object_Box_Layout", eolian_type::callback_, {"Evas.h"}}, - {"Evas_Object *", eolian_type::simple_, false, false, "evas::object", {"canvas/evas_object.eo.hh"}}, - {"char *", eolian_type::simple_, false, true, "std::unique_ptr<char*>", {"memory"}}, - {"const Eina_Inlist *", eolian_type::complex_, false, false, "efl::eina::range_inlist", {"eina-cxx/eina_inlist.hh"}}, - {"const Eina_List *", eolian_type::complex_, false, false, "efl::eina::range_list", {"eina-cxx/eina_ptrlist.hh"}}, - {"const char *", eolian_type::simple_, false, false, "std::string", {"string"}}, + {"Evas_Object *", eolian_type::simple_, false, false, true, "::evas::object", {"canvas/evas_object.eo.hh"}}, + {"char *", eolian_type::simple_, false, true, true, "std::unique_ptr<char*>", {"memory"}}, + {"const Eina_Inlist *", eolian_type::complex_, false, false, true, "::efl::eina::range_inlist", {"eina-cxx/eina_inlist.hh"}}, + {"const Eina_List *", eolian_type::complex_, false, false, true, "::efl::eina::range_list", {"eina-cxx/eina_ptrlist.hh"}}, + {"const char *", eolian_type::simple_, false, false, true, "std::string", {"string"}}, }; } diff --git a/src/bindings/eina_cxx/eina_accessor.hh b/src/bindings/eina_cxx/eina_accessor.hh index e64d0ef698..b867f14248 100644 --- a/src/bindings/eina_cxx/eina_accessor.hh +++ b/src/bindings/eina_cxx/eina_accessor.hh @@ -4,7 +4,7 @@ #include <Eina.h> #include <eina_error.hh> #include <eina_throw.hh> -#include <eina_eo_base_fwd.hh> +#include <eina_eo_concrete_fwd.hh> #include <memory> #include <iterator> @@ -151,7 +151,7 @@ template <typename T, typename Enable = T> struct accessor; template <typename T> -struct accessor<T, typename std::enable_if< ! std::is_base_of<efl::eo::base, T>::value, T>::type> +struct accessor<T, typename std::enable_if< ! std::is_base_of<::efl::eo::concrete, T>::value, T>::type> : accessor_common_base<T> { typedef accessor_common_base<T> _base_type; @@ -262,7 +262,7 @@ struct accessor<T, typename std::enable_if< ! std::is_base_of<efl::eo::base, T>: }; template <typename T> -struct accessor<T, typename std::enable_if<std::is_base_of<efl::eo::base, T>::value, T>::type> +struct accessor<T, typename std::enable_if<std::is_base_of<::efl::eo::concrete, T>::value, T>::type> : accessor_common_base<T> { typedef accessor_common_base<T> _base_type; @@ -404,7 +404,7 @@ struct accessor_iterator; * Random access iterator for <tt>eina::accessor</tt>. */ template <typename T> -struct accessor_iterator<T, typename std::enable_if< ! std::is_base_of<efl::eo::base, T>::value, T>::type> +struct accessor_iterator<T, typename std::enable_if< ! std::is_base_of<::efl::eo::concrete, T>::value, T>::type> { typedef T value_type; /**< Type of the elements. */ typedef value_type* pointer; /**< Pointer to element type. */ @@ -553,10 +553,10 @@ struct accessor_iterator<T, typename std::enable_if< ! std::is_base_of<efl::eo:: }; /** - * Specialization for all data types that are not derivated from efl::eo::base. + * Specialization for all data types that are not derivated from efl::eo::concrete. */ template <typename T> -struct accessor_iterator<T, typename std::enable_if<std::is_base_of<efl::eo::base, T>::value, T>::type> +struct accessor_iterator<T, typename std::enable_if<std::is_base_of<::efl::eo::concrete, T>::value, T>::type> { typedef T value_type; /**< Type of the elements. */ typedef value_type* pointer; /**< Pointer to element type. */ diff --git a/src/bindings/eina_cxx/eina_array.hh b/src/bindings/eina_cxx/eina_array.hh index 75346bc5fc..eb9e5578aa 100644 --- a/src/bindings/eina_cxx/eina_array.hh +++ b/src/bindings/eina_cxx/eina_array.hh @@ -3,7 +3,7 @@ #include <Eo.h> #include <eina_ptrarray.hh> -#include <eina_eo_base_fwd.hh> +#include <eina_eo_concrete_fwd.hh> #include <iostream> @@ -132,7 +132,7 @@ struct _ptr_eo_array_iterator : _ptr_array_iterator<Eo> }; template <typename T, typename CloneAllocator> -class array<T, CloneAllocator, typename std::enable_if<std::is_base_of<efl::eo::base, T>::value>::type> +class array<T, CloneAllocator, typename std::enable_if<std::is_base_of<::efl::eo::concrete, T>::value>::type> : ptr_array<Eo, typename std::conditional <std::is_same<CloneAllocator, default_clone_allocator_placeholder>::value , eo_clone_allocator, CloneAllocator>::type> diff --git a/src/bindings/eina_cxx/eina_eo_base_fwd.hh b/src/bindings/eina_cxx/eina_eo_base_fwd.hh deleted file mode 100644 index b160a6d049..0000000000 --- a/src/bindings/eina_cxx/eina_eo_base_fwd.hh +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef EINA_EO_BASE_FWD_HH -#define EINA_EO_BASE_FWD_HH - -#include <Eo.h> -#include <type_traits> - -namespace efl { namespace eo { - -struct base; - -} } - -namespace std { -template <> -struct is_base_of< ::efl::eo::base, ::Eo > : std::false_type {}; -template <> -struct is_base_of< ::efl::eo::base, const ::Eo > : std::false_type {}; -template <> -struct is_base_of< ::efl::eo::base, volatile ::Eo > : std::false_type {}; -template <> -struct is_base_of< ::efl::eo::base, const volatile ::Eo > : std::false_type {}; - -template <> -struct is_base_of< const ::efl::eo::base, ::Eo > : std::false_type {}; -template <> -struct is_base_of< const ::efl::eo::base, const ::Eo > : std::false_type {}; -template <> -struct is_base_of< const ::efl::eo::base, volatile ::Eo > : std::false_type {}; -template <> -struct is_base_of< const ::efl::eo::base, const volatile ::Eo > : std::false_type {}; -} - -#endif diff --git a/src/bindings/eina_cxx/eina_eo_concrete_fwd.hh b/src/bindings/eina_cxx/eina_eo_concrete_fwd.hh new file mode 100644 index 0000000000..3e96e8fe30 --- /dev/null +++ b/src/bindings/eina_cxx/eina_eo_concrete_fwd.hh @@ -0,0 +1,33 @@ +#ifndef EINA_EO_CONCRETE_FWD_HH +#define EINA_EO_CONCRETE_FWD_HH + +#include <Eo.h> +#include <type_traits> + +namespace efl { namespace eo { + +struct concrete; + +} } + +namespace std { +template <> +struct is_base_of< ::efl::eo::concrete, ::Eo > : std::false_type {}; +template <> +struct is_base_of< ::efl::eo::concrete, const ::Eo > : std::false_type {}; +template <> +struct is_base_of< ::efl::eo::concrete, volatile ::Eo > : std::false_type {}; +template <> +struct is_base_of< ::efl::eo::concrete, const volatile ::Eo > : std::false_type {}; + +template <> +struct is_base_of< const ::efl::eo::concrete, ::Eo > : std::false_type {}; +template <> +struct is_base_of< const ::efl::eo::concrete, const ::Eo > : std::false_type {}; +template <> +struct is_base_of< const ::efl::eo::concrete, volatile ::Eo > : std::false_type {}; +template <> +struct is_base_of< const ::efl::eo::concrete, const volatile ::Eo > : std::false_type {}; +} + +#endif diff --git a/src/bindings/eina_cxx/eina_list.hh b/src/bindings/eina_cxx/eina_list.hh index b81097139f..760ada3963 100644 --- a/src/bindings/eina_cxx/eina_list.hh +++ b/src/bindings/eina_cxx/eina_list.hh @@ -227,7 +227,7 @@ public: }; template <typename T, typename CloneAllocator> -class list<T, CloneAllocator, typename std::enable_if<std::is_base_of<efl::eo::base, T>::value>::type> +class list<T, CloneAllocator, typename std::enable_if<std::is_base_of<::efl::eo::concrete, T>::value>::type> : ptr_list<Eo, typename std::conditional <std::is_same<CloneAllocator, default_clone_allocator_placeholder>::value , eo_clone_allocator, CloneAllocator>::type> @@ -482,7 +482,7 @@ public: }; template <typename T> -class range_list<T, typename std::enable_if<std::is_base_of<efl::eo::base, T>::value>::type> +class range_list<T, typename std::enable_if<std::is_base_of<::efl::eo::concrete, T>::value>::type> : range_ptr_list<typename std::conditional<std::is_const<T>::value, Eo const, Eo>::type> { typedef range_ptr_list<typename std::conditional<std::is_const<T>::value, Eo const, Eo>::type> _base_type; diff --git a/src/bindings/eina_cxx/eina_ptrlist.hh b/src/bindings/eina_cxx/eina_ptrlist.hh index d6bc9dc7ed..e06f436a19 100644 --- a/src/bindings/eina_cxx/eina_ptrlist.hh +++ b/src/bindings/eina_cxx/eina_ptrlist.hh @@ -6,7 +6,7 @@ #include <eina_lists_auxiliary.hh> #include <eina_type_traits.hh> #include <eina_accessor.hh> -#include <eina_eo_base_fwd.hh> +#include <eina_eo_concrete_fwd.hh> #include <eina_iterator.hh> #include <eina_throw.hh> diff --git a/src/bindings/eo_cxx/Eo.hh b/src/bindings/eo_cxx/Eo.hh index a324e1c43c..a6f0423724 100644 --- a/src/bindings/eo_cxx/Eo.hh +++ b/src/bindings/eo_cxx/Eo.hh @@ -1,7 +1,7 @@ #ifndef EFL_CXX_EO_HH #define EFL_CXX_EO_HH -#include <eo_base.hh> +#include <eo_concrete.hh> #include <eo_init.hh> #include <eo_wref.hh> #include <eo_inherit.hh> diff --git a/src/bindings/eo_cxx/eo_base.hh b/src/bindings/eo_cxx/eo_concrete.hh index 020816a69a..4d379a618b 100644 --- a/src/bindings/eo_cxx/eo_base.hh +++ b/src/bindings/eo_cxx/eo_concrete.hh @@ -1,10 +1,9 @@ - /// -/// @file eo_base.hh +/// @file eo_concrete.hh /// -#ifndef EFL_CXX_EO_BASE_HH -#define EFL_CXX_EO_BASE_HH +#ifndef EFL_CXX_EO_CONCRETE_HH +#define EFL_CXX_EO_CONCRETE_HH #include <cassert> #include <stdexcept> @@ -27,41 +26,42 @@ namespace efl { namespace eo { /// @addtogroup Efl_Cxx_API /// @{ -/// @brief A binding to the <em>EO Base Class</em>. +/// @brief Creates concrete versions for <em>Eo</em> wrappers. /// -/// This class implements C++ wrappers to all the <em>EO Base</em> -/// operations. +/// This class creates the concrete version of all C++ <em>Eo</em> wrappers. +/// It holds the Eo pointer that is used on all operations and provides some +/// functions for manipulating it. /// -struct base +struct concrete { /// @brief Class constructor. /// /// @param eo The <em>EO Object</em>. /// - /// efl::eo::base constructors semantics are that of stealing the + /// efl::eo::concrete constructors semantics are that of stealing the /// <em>EO Object</em> lifecycle management. Its constructors do not /// increment the <em>EO</em> reference counter but the destructors /// do decrement. /// - explicit base(Eo* eo) : _eo_raw(eo) + explicit concrete(Eo* eo) : _eo_raw(eo) { } /// @brief Class destructor. /// - ~base() + ~concrete() { if(_eo_raw) detail::unref(_eo_raw); } - base(base const& other) + concrete(concrete const& other) { if(other._eo_raw) _eo_raw = detail::ref(other._eo_raw); } - base(base&& other) + concrete(concrete&& other) { if(_eo_raw) detail::unref(_eo_raw); _eo_raw = other._eo_raw; @@ -70,7 +70,7 @@ struct base /// @brief Assignment operator. /// - base& operator=(base const& other) + concrete& operator=(concrete const& other) { if(_eo_raw) { @@ -82,7 +82,7 @@ struct base return *this; } - base& operator=(base&& other) + concrete& operator=(concrete&& other) { if(_eo_raw) { @@ -100,7 +100,7 @@ struct base /// Eo* _eo_ptr() const { return _eo_raw; } - /// @brief Releases the reference from this wrapper object and + /// @brief Releases the reference from this concrete object and /// return the pointer to the <em>EO Object</em> stored in this /// instance. /// @@ -132,85 +132,27 @@ struct base /// /// @param parent The new parent. /// - void parent_set(base parent) + void parent_set(concrete parent) { detail::parent_set(_eo_raw, parent._eo_ptr()); } /// @brief Get the parent of this object. /// - /// @return An @ref efl::eo::base instance that binds the parent + /// @return An @ref efl::eo::concrete instance that binds the parent /// object. Returns NULL if there is no parent. /// - eina::optional<base> parent_get() + eina::optional<concrete> parent_get() { Eo *r = detail::parent_get(_eo_raw); if(!r) return nullptr; else { detail::ref(r); // XXX eo_parent_get does not call eo_ref so we may. - return base(r); + return concrete(r); } } - /// @brief Set generic data to object. - /// - /// @param key The key associated with the data. - /// @param data The data to set. - /// @param free_func A pointer to the function that frees the - /// data. @c (::eo_key_data_free_func*)0 is valid. - /// - void base_data_set(const char *key, const void *data, ::eo_key_data_free_func func) - { - detail::base_data_set(_eo_raw, key, data, func); - } - - /// @brief Get generic data from object. - /// - /// @param key The key associated with desired data. - /// @return A void pointer to the data. - /// - void* base_data_get(const char *key) - { - return detail::base_data_get(_eo_raw, key); - } - - /// @brief Delete generic data from object. - /// - /// @param key The key associated with the data. - /// - void base_data_del(const char *key) - { - detail::base_data_del(_eo_raw, key); - } - - /// @brief Freeze any event directed to this object. - /// - /// Prevents event callbacks from being called for this object. - /// - void event_freeze() - { - detail::event_freeze(_eo_raw); - } - - /// @brief Thaw the events of this object. - /// - /// Let event callbacks be called for this object. - /// - void event_thaw() - { - detail::event_thaw(_eo_raw); - } - - /// @brief Get the event freeze count for this object. - /// - /// @return The event freeze count for this object. - /// - int event_freeze_get() - { - return detail::event_freeze_get(_eo_raw); - } - /// @brief Get debug information of this object. /// /// @return The root node of the debug information tree. @@ -228,15 +170,14 @@ struct base } protected: Eo* _eo_raw; ///< The opaque <em>EO Object</em>. - }; -inline bool operator==(base const& lhs, base const& rhs) +inline bool operator==(concrete const& lhs, concrete const& rhs) { return lhs._eo_ptr() == rhs._eo_ptr(); } -inline bool operator!=(base const& lhs, base const& rhs) +inline bool operator!=(concrete const& lhs, concrete const& rhs) { return !(lhs == rhs); } @@ -247,14 +188,14 @@ template <typename T> struct extension_inheritance; template<> -struct extension_inheritance<base> +struct extension_inheritance<concrete> { template <typename T> struct type { - operator base() const + operator concrete() const { - return base(eo_ref(static_cast<T const*>(this)->_eo_ptr())); + return concrete(eo_ref(static_cast<T const*>(this)->_eo_ptr())); } }; @@ -288,7 +229,7 @@ T downcast(U object) } /// -/// @brief Type used to hold the parent passed to base Eo C++ +/// @brief Type used to hold the parent passed to concrete Eo C++ /// constructors. /// struct parent_type @@ -298,11 +239,11 @@ struct parent_type /// /// @brief The expression type declaring the assignment operator used -/// in the parent argument of the base Eo C++ class. +/// in the parent argument of the concrete Eo C++ class. /// struct parent_expr { - parent_type operator=(efl::eo::base const& parent) const + parent_type operator=(efl::eo::concrete const& parent) const { return { parent._eo_ptr() }; } @@ -327,4 +268,4 @@ parent_expr const parent = {}; } } // namespace efl { namespace eo { -#endif // EFL_CXX_EO_BASE_HH +#endif // EFL_CXX_EO_CONCRETE_HH diff --git a/src/bindings/eo_cxx/eo_cxx_interop.hh b/src/bindings/eo_cxx/eo_cxx_interop.hh index d8292961f1..b0ca1ed445 100644 --- a/src/bindings/eo_cxx/eo_cxx_interop.hh +++ b/src/bindings/eo_cxx/eo_cxx_interop.hh @@ -39,19 +39,19 @@ to_c(bool* x) } template <typename T> -T to_c(T const& v, typename std::enable_if<!std::is_convertible<T*, efl::eo::base*>::value>::type* = 0) +T to_c(T const& v, typename std::enable_if<!std::is_convertible<T*, ::efl::eo::concrete*>::value>::type* = 0) { return v; } template <typename T> -Eo* to_c(T const& v, typename std::enable_if<std::is_convertible<T*, efl::eo::base*>::value>::type* = 0) +Eo* to_c(T const& v, typename std::enable_if<std::is_convertible<T*, ::efl::eo::concrete*>::value>::type* = 0) { return v._eo_ptr(); } template <typename T> -Eo** to_c(T* v, typename std::enable_if<std::is_convertible<T*, efl::eo::base*>::value>::type* = 0) +Eo** to_c(T* v, typename std::enable_if<std::is_convertible<T*, ::efl::eo::concrete*>::value>::type* = 0) { static_assert(sizeof(T) == sizeof(Eo*), ""); return static_cast<Eo**>(static_cast<void*>(v)); @@ -137,7 +137,7 @@ struct traits template <typename T> struct traits - <T, typename std::enable_if<std::is_base_of<efl::eo::base, T>::value>::type> + <T, typename std::enable_if<std::is_base_of<::efl::eo::concrete, T>::value>::type> { typedef Eo* type; }; @@ -193,7 +193,7 @@ to_cxx(Eina_Iterator* x, std::tuple<std::false_type, Args...>, tag< efl::eina::i template <typename T, typename ...Args> T to_cxx(Eo const* x, std::tuple<std::false_type, Args...>, tag< T > - , typename std::enable_if<std::is_base_of<efl::eo::base, T>::value>* = 0) + , typename std::enable_if<std::is_base_of<::efl::eo::concrete, T>::value>* = 0) { // Workaround for erroneous constness return T{ ::eo_ref(const_cast<Eo*>(x))}; @@ -202,7 +202,7 @@ to_cxx(Eo const* x, std::tuple<std::false_type, Args...>, tag< T > template <typename T, typename ...Args> T to_cxx(Eo const* x, std::tuple<std::true_type, Args...>, tag< T > - , typename std::enable_if<std::is_base_of<efl::eo::base, T>::value>* = 0) + , typename std::enable_if<std::is_base_of<::efl::eo::concrete, T>::value>* = 0) { // Workaround for erroneous constness return T{const_cast<Eo*>(x)}; diff --git a/src/bindings/eo_cxx/eo_inherit.hh b/src/bindings/eo_cxx/eo_inherit.hh index d81c70fa60..c04e3ceb88 100644 --- a/src/bindings/eo_cxx/eo_inherit.hh +++ b/src/bindings/eo_cxx/eo_inherit.hh @@ -40,7 +40,7 @@ void inherit_constructor(void* this_, Args args); /// /// The derived class @p D will inherit all EO operations and event /// callbacks from the parent class @p P, as well as from the <c>Base -/// Class</c> (@ref efl::eo::base) since every EO C++ Class must +/// Class</c> (@ref efl::eo::concrete) since every EO C++ Class must /// inherit from it. /// /// efl::eo::inherit makes use of meta-template elements to build (in diff --git a/src/lib/eolian_cxx/eo_types.hh b/src/lib/eolian_cxx/eo_types.hh index 15f88e21fd..42abe397cd 100644 --- a/src/lib/eolian_cxx/eo_types.hh +++ b/src/lib/eolian_cxx/eo_types.hh @@ -14,7 +14,7 @@ struct eo_parameter; struct eo_function; struct eo_event; -typedef std::vector<std::string> extensions_container_type; +typedef std::vector<std::string> parents_container_type; typedef std::vector<std::string> includes_container_type; typedef std::vector<eo_constructor> constructors_container_type; typedef std::vector<eo_function> functions_container_type; @@ -33,7 +33,7 @@ struct eolian_type , category(unknown_) , is_const(false) , is_own(false) - , is_out(false) + , is_class(false) , binding() , includes() {} @@ -42,13 +42,14 @@ struct eolian_type category_type category_, bool is_const_, bool is_own_, + bool is_class_, std::string binding_, includes_container_type includes_) : native(native_) , category(category_) , is_const(is_const_) , is_own(is_own_) - , is_out(false) + , is_class(is_class_) , binding(binding_) , includes(includes_) { @@ -59,7 +60,7 @@ struct eolian_type eolian_type(std::string native_, category_type category_, includes_container_type const& includes_) - : eolian_type(native_, category_, false, false, "", includes_) + : eolian_type(native_, category_, false, false, false, "", includes_) { assert(category == callback_); } @@ -68,20 +69,48 @@ struct eolian_type category_type category; bool is_const; bool is_own; - bool is_out; + bool is_class; std::string binding; includes_container_type includes; }; -typedef std::vector<eolian_type> eolian_type_instance; +typedef std::vector<eolian_type> eolian_type_container; + +struct eolian_type_instance +{ + eolian_type_instance() + : is_out(false) + , parts() + {} + + eolian_type_instance(std::initializer_list<eolian_type> il, + bool is_out_ = false) + : is_out(is_out_) + , parts(il) + {} + + explicit eolian_type_instance(std::size_t size) + : is_out(false) + , parts(size) + {} + + bool empty() const { return parts.empty(); } + std::size_t size() const { return parts.size(); } + + eolian_type& front() { return parts.front(); } + eolian_type const& front() const { return parts.front(); } + + bool is_out; + eolian_type_container parts; +}; const efl::eolian::eolian_type -void_type { "void", efl::eolian::eolian_type::simple_, false, false, "", {} }; +void_type { "void", efl::eolian::eolian_type::simple_, false, false, false, "", {} }; inline bool type_is_void(eolian_type_instance const& type) { - return type.empty() || type[0].native.compare("void") == 0; + return type.empty() || type.front().native.compare("void") == 0; } inline bool @@ -98,16 +127,22 @@ type_is_binding(eolian_type_instance const& type) } inline bool -type_is_out(eolian_type const& type) +type_is_out(eolian_type_instance const& type) { return type.is_out; } inline bool -type_is_out(eolian_type_instance const& type) +type_is_class(eolian_type const& type) +{ + return type.is_class; +} + +inline bool +type_is_class(eolian_type_instance const& type) { assert(!type.empty()); - return type_is_out(type.front()); + return type_is_class(type.front()); } inline eolian_type @@ -116,6 +151,7 @@ type_to_native(eolian_type const& type) eolian_type native(type); native.binding.clear(); native.category = eolian_type::simple_; + native.is_class = false; return native; } @@ -179,8 +215,7 @@ struct eo_class eo_class_type type; std::string name; std::string eo_name; - std::string parent; - extensions_container_type extensions; + parents_container_type parents; constructors_container_type constructors; functions_container_type functions; events_container_type events; @@ -227,7 +262,7 @@ struct eo_event inline bool function_is_void(eo_function const& func) { - return func.ret.empty() || func.ret[0].native.compare("void") == 0; + return func.ret.empty() || func.ret.front().native.compare("void") == 0; } inline bool diff --git a/src/lib/eolian_cxx/eo_validate.hh b/src/lib/eolian_cxx/eo_validate.hh index 027c8fced1..1e23751f4f 100644 --- a/src/lib/eolian_cxx/eo_validate.hh +++ b/src/lib/eolian_cxx/eo_validate.hh @@ -23,7 +23,7 @@ _is_valid(eolian_type_instance const& type) { // if (type.empty() || (*type.rbegin()).category == eolian_type::complex_) // return false; - for (auto rit = type.rbegin(), last = type.rend(); rit != last; ++rit) + for (auto rit = type.parts.rbegin(), last = type.parts.rend(); rit != last; ++rit) { if ((*rit).binding.empty() && (*rit).category == eolian_type::complex_) return false; diff --git a/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh index c7a9bbba80..9e1ab5877d 100644 --- a/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh +++ b/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh @@ -9,6 +9,7 @@ #include "tab.hh" #include "comment.hh" #include "parameters_generator.hh" +#include "namespace_generator.hh" namespace efl { namespace eolian { namespace grammar { @@ -27,34 +28,6 @@ operator<<(std::ostream& out, class_name const& x) return out; } -struct class_extensions -{ - eo_class const& _cls; - class_extensions(eo_class const& cls) - : _cls(cls) - {} -}; - -inline std::ostream& -operator<<(std::ostream& out, class_extensions const& x) -{ - eo_class const& cls = x._cls; - extensions_container_type::const_iterator it, first = cls.extensions.begin(); - extensions_container_type::const_iterator last = cls.extensions.end(); - for (it = first; it != last; ++it) - { - if (it != first) out << ",\n"; - out << tab(2) - << "efl::eo::detail::extension_inheritance<" - << *it << ">::template type< ::"; - if(!cls.name_space.empty()) - out << cls.name_space << "::"; - out << cls.name << ">"; - } - out << endl; - return out; -} - struct class_inheritance { eo_class const& _cls; @@ -68,12 +41,14 @@ operator<<(std::ostream& out, class_inheritance const& x) { eo_class const& cls = x._cls; - out << class_name(cls.parent); - if (cls.extensions.size() > 0) + parents_container_type::const_iterator it, + first = cls.parents.cbegin(), + last = cls.parents.cend(); + for (it = first; it != last; ++it) { - out << "," << endl << class_extensions(cls); + out << tab(2) << (it == first ? ": " : ", ") + << "::" << abstract_namespace << "::" << *it << endl; } - out << endl; return out; } @@ -208,14 +183,14 @@ operator<<(std::ostream& out, functors_constructor_methods const& x) return out; } -struct functions_constructor_methods +struct constructor_method_function_declarations { eo_class const& _cls; - functions_constructor_methods(eo_class const& cls) : _cls(cls) {} + constructor_method_function_declarations(eo_class const& cls) : _cls(cls) {} }; inline std::ostream& -operator<<(std::ostream& out, functions_constructor_methods const& x) +operator<<(std::ostream& out, constructor_method_function_declarations const& x) { constructors_container_type::const_iterator it, first = x._cls.constructors.cbegin(), @@ -224,14 +199,56 @@ operator<<(std::ostream& out, functions_constructor_methods const& x) { eo_constructor const& c = *it; - out << comment(c.comment, 1) + // "eo_constructor" is already called in the eo_add_ref macro (used in + // _ctors_call). + // Creating a function with this name yields an error in the eo_add_ref + // macro expansion, because "eo_constructor" will refers to the class + // function instead of the Eo.Base function which is intended. + if (c.name == "eo_constructor") + { + continue; + } + + out << comment(c.comment, 0) << template_parameters_declaration(c.params, 1) << tab(1) << constructor_functor_type_decl(c) << " " << c.name << "(" - << parameters_declaration(c.params) << ")" << endl - << tab(1) << "{" << endl - << tab(2) << "return " << constructor_functor_type_decl(c) << "(" + << parameters_declaration(c.params) << ") const;" << endl << endl; + } + + return out; +} + +struct constructor_method_function_definitions +{ + eo_class const& _cls; + constructor_method_function_definitions(eo_class const& cls) : _cls(cls) {} +}; + +inline std::ostream& +operator<<(std::ostream& out, constructor_method_function_definitions const& x) +{ + constructors_container_type::const_iterator it, + first = x._cls.constructors.cbegin(), + last = x._cls.constructors.cend(); + for (it = first; it != last; ++it) + { + eo_constructor const& c = *it; + + // Same explanation as the one in constructor_method_function_declarations + if (c.name == "eo_constructor") + { + continue; + } + + out << template_parameters_declaration(c.params, 0) + << "inline " << abstract_full_name(x._cls) + << "::" << constructor_functor_type_decl(c) << " " + << abstract_full_name(x._cls, false) << "::" << c.name << "(" + << parameters_declaration(c.params) << ") const" << endl + << "{" << endl + << tab(1) << "return " << constructor_functor_type_decl(c) << "(" << parameters_forward(c.params) << ");" << endl - << tab(1) << "}" << endl << endl; + << "}" << endl << endl; } return out; @@ -248,10 +265,6 @@ struct constructor_with_constructor_methods inline std::ostream& operator<<(std::ostream& out, constructor_with_constructor_methods const& x) { - // - // TODO Require constructor methods of all base classes ? - // - unsigned cb_count = 0; constructors_container_type::const_iterator it, @@ -296,7 +309,7 @@ operator<<(std::ostream& out, constructor_with_constructor_methods const& x) } assert(cb_idx == cb_count); } - out << "efl::eo::parent_type _p = (efl::eo::parent = nullptr))" << endl + out << "::efl::eo::parent_type _p = (::efl::eo::parent = nullptr))" << endl << tab(2) << ": " << x._cls.name << "(_ctors_call("; for (it = first; it != last; ++it) { @@ -325,7 +338,7 @@ operator<<(std::ostream& out, constructor_eo const& x) out << comment(doc, 1) << tab(1) << "explicit " << x._cls.name << "(Eo* eo)" << endl - << tab(2) << ": " << class_name(x._cls.parent) << "(eo)" << endl + << tab(2) << ": ::efl::eo::concrete(eo)" << endl << tab(1) << "{}" << endl << endl; out << comment( @@ -335,7 +348,7 @@ operator<<(std::ostream& out, constructor_eo const& x) ) << tab(1) << "explicit " << x._cls.name << "(std::nullptr_t)" << endl - << tab(2) << ": " << class_name(x._cls.parent) << "(nullptr)" << endl + << tab(2) << ": ::efl::eo::concrete(nullptr)" << endl << tab(1) << "{}" << endl << endl; return out; } @@ -355,7 +368,7 @@ operator<<(std::ostream& out, copy_constructor const& x) out << comment(doc, 1) << tab(1) << x._cls.name << "(" << x._cls.name << " const& other)" << endl - << tab(2) << ": " << class_name(x._cls.parent) + << tab(2) << ": " << x._cls.name << "(eo_ref(other._eo_ptr()))" << endl << tab(1) << "{}" << endl << endl; return out; @@ -427,7 +440,7 @@ operator<<(std::ostream& out, function_call_constructor_methods const& x) } assert(cb_idx == cb_count); - out << "efl::eo::parent_type _p)" << endl + out << "::efl::eo::parent_type _p)" << endl << tab(1) << "{" << endl << tab(2) << "Eo* _ret_eo = eo_add_ref(" << x._cls.eo_name << ", _p._eo_raw, "; for (it = first; it != last; ++it) @@ -449,7 +462,7 @@ operator<<(std::ostream& out, function_call_constructor_methods const& x) d.out << tab(2) << "eo_do(_ret_eo," << endl << tab(3) << "eo_event_callback_add(EO_EV_DEL, " - << "&efl::eolian::free_callback_calback<F" << cb_idx++ + << "&::efl::eolian::free_callback_calback<F" << cb_idx++ << ">, _c" << (it-first) << "." << callback_tmp(d.name) << "));" << endl; }) diff --git a/src/lib/eolian_cxx/grammar/eo_class_events_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_events_generator.hh index 596bb8b528..eeb900b398 100644 --- a/src/lib/eolian_cxx/grammar/eo_class_events_generator.hh +++ b/src/lib/eolian_cxx/grammar/eo_class_events_generator.hh @@ -4,7 +4,7 @@ #include <iosfwd> -#include "eo_types.hh" +#include "type_generator.hh" #include "tab.hh" #include "comment.hh" @@ -50,14 +50,14 @@ operator<<(std::ostream& out, event_callback_add const& x) << tab(1) << "{" << endl << tab(2) << "typedef typename std::remove_reference<F>::type function_type;" << endl << tab(2) << "::std::unique_ptr<function_type> f ( new function_type(std::move(callback_)) );" << endl - << tab(2) << "eo_do(" << add_cast_to_t(x._add_cast_to_t) << "_eo_ptr()," << endl + << tab(2) << "eo_do(" << add_cast_to_t(x._add_cast_to_t) << "_concrete_eo_ptr()," << endl << tab(4) << "eo_event_callback_priority_add" << endl << tab(4) << "(" << x._event.eo_name << ", priority_," << endl - << tab(4) << "&efl::eo::_detail::event_callback<" << x._cls.name_space << "::" << x._cls.name << ", function_type>, f.get()));" << endl + << tab(4) << "&::efl::eo::_detail::event_callback<" << full_name(x._cls) << ", function_type>, f.get()));" << endl << tab(2) << "return ::efl::eo::make_signal_connection" << endl << tab(3) << "(f, " << add_cast_to_t(x._add_cast_to_t) - << "_eo_ptr(), &efl::eo::_detail::event_callback<" - << x._cls.name_space << "::" << x._cls.name << ", function_type>," << endl + << "_concrete_eo_ptr(), &::efl::eo::_detail::event_callback<" + << full_name(x._cls) << ", function_type>," << endl << tab(3) << x._event.eo_name << " );" << endl << tab(1) << "}" << endl; return out; @@ -79,7 +79,7 @@ operator<<(std::ostream& out, event_callback_call const& x) << tab(1) << "void" << endl << tab(1) << "callback_" << x._event.name << "_call(T* info)" << endl << tab(1) << "{" << endl - << tab(2) << "eo_do(" << add_cast_to_t(x._add_cast_to_t) << "_eo_ptr(), eo_event_callback_call" << endl + << tab(2) << "eo_do(" << add_cast_to_t(x._add_cast_to_t) << "_concrete_eo_ptr(), eo_event_callback_call" << endl << tab(4) << "(" << x._event.eo_name << ", info));" << endl << tab(1) << "}" << endl; return out; @@ -101,6 +101,7 @@ operator<<(std::ostream& out, events const& x) out << event_callback_add(e, x._cls, x._add_cast_to_t) << endl << event_callback_call(e, x._add_cast_to_t); } + out << endl; return out; } diff --git a/src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh index 9c48106de4..f375fd7ca1 100644 --- a/src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh +++ b/src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh @@ -9,6 +9,7 @@ #include "comment.hh" #include "parameters_generator.hh" #include "type_generator.hh" +#include "namespace_generator.hh" namespace efl { namespace eolian { namespace grammar { @@ -27,60 +28,110 @@ operator<<(std::ostream& out, function_call const& x) << "(" << parameters_forward_to_c(x._func.params) << ")"; } -struct function +struct function_declaration { + eo_class const& _cls; eo_function const& _func; - function(eo_function const& func) : _func(func) {} + function_declaration(eo_class const& cls, eo_function const& func) + : _cls(cls), _func(func) + {} }; inline std::ostream& -operator<<(std::ostream& out, function const& x) +operator<<(std::ostream& out, function_declaration const& x) { eo_function const& func = x._func; - out << comment(x._func.comment, 1); - out << template_parameters_declaration(func.params, 1); + out << comment(x._func.comment, 1) + << template_parameters_declaration(func.params, 1) + << tab(1); - if (function_is_static(func)) - out << tab(1) << "static "; + bool is_static = function_is_static(func); + if (is_static) + out << "static "; - out << tab(1) - << reinterpret_type(func.ret) << " " << func.name << "(" + out << reinterpret_type(func.ret) << " " << func.name << "(" << parameters_declaration(func.params) - << ") const" << endl - << tab(1) << "{" << endl; + << (is_static ? ");" : ") const;") << endl << endl; + + return out; +} + +struct function_definition +{ + eo_class const& _cls; + eo_function const& _func; + function_definition(eo_class const& cls, eo_function const& func) + : _cls(cls), _func(func) + {} +}; + +inline std::ostream& +operator<<(std::ostream& out, function_definition const& x) +{ + eo_function const& func = x._func; + + bool is_static = function_is_static(func); + + out << template_parameters_declaration(func.params, 0) + << "inline " << reinterpret_type(func.ret) << " " + << abstract_full_name(x._cls, false) << "::" << func.name << "(" + << parameters_declaration(func.params) + << (is_static ? ")" : ") const") << endl + << "{" << endl; if (!function_is_void(func)) - out << tab(2) + out << tab(1) << func.ret.front().native << " _tmp_ret;" << endl; - out << callbacks_heap_alloc("_eo_ptr()", func.params, 2); + if (!is_static) + out << callbacks_heap_alloc("_concrete_eo_ptr()", func.params, 1); + + // TODO : register free callback for static methods - out << tab(2) - << "eo_do(_eo_ptr(), " << function_call(x._func) << ");" << endl; + out << tab(1) << "eo_do(" + << (is_static ? "_eo_class(), " : "_concrete_eo_ptr(), ") + << function_call(x._func) << ");" << endl; if (!function_is_void(func)) - out << tab(2) << "return " << to_cxx(func.ret, "_tmp_ret") << ";" << endl; + out << tab(1) << "return " << to_cxx(func.ret, "_tmp_ret") << ";" << endl; + + out << "}" << endl << endl; + return out; +} + +struct function_declarations +{ + eo_class const& _cls; + function_declarations(eo_class const& cls) + : _cls(cls) + {} +}; - out << tab(1) << "}" << endl; +inline std::ostream& +operator<<(std::ostream& out, function_declarations const& x) +{ + for (eo_function const& f : x._cls.functions) + { + out << function_declaration(x._cls, f) << endl; + } return out; } -struct functions +struct function_definitions { - functions_container_type const& _funcs; - functions(functions_container_type const& funcs) : _funcs(funcs) {} + eo_class const& _cls; + function_definitions(eo_class const& cls) + : _cls(cls) + {} }; inline std::ostream& -operator<<(std::ostream& out, functions const& x) +operator<<(std::ostream& out, function_definitions const& x) { - functions_container_type::const_iterator it, - first = x._funcs.begin(), - last = x._funcs.end(); - for (it = first; it != last; it++) + for (eo_function const& f : x._cls.functions) { - out << function(*it) << endl; + out << function_definition(x._cls, f) << endl; } return out; } diff --git a/src/lib/eolian_cxx/grammar/eo_class_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_generator.hh index 2b82d845a5..f54485cfa6 100644 --- a/src/lib/eolian_cxx/grammar/eo_class_generator.hh +++ b/src/lib/eolian_cxx/grammar/eo_class_generator.hh @@ -8,6 +8,7 @@ #include "eo_types.hh" #include "tab.hh" #include "comment.hh" +#include "namespace_generator.hh" #include "eo_class_constructors_generator.hh" #include "eo_class_functions_generator.hh" #include "eo_class_events_generator.hh" @@ -30,28 +31,112 @@ operator<<(std::ostream& out, eo_class_getter const& x) return out; } +struct concrete_eo_ptr_getter +{ + eo_class const& _cls; + concrete_eo_ptr_getter(eo_class const& cls) : _cls(cls) {} +}; + +inline std::ostream& +operator<<(std::ostream& out, concrete_eo_ptr_getter const&) +{ + out << tab(1) << "Eo* _concrete_eo_ptr() const" << endl + << tab(1) << "{" << endl + << tab(2) << "return static_cast<::efl::eo::concrete const*>(static_cast<void const*>(this))->_eo_ptr();" << endl + << tab(1) << "}" << endl << endl; + return out; +} + +struct class_implicit_conversion_declaration +{ + eo_class const& _cls; + class_implicit_conversion_declaration(eo_class const& cls) : _cls(cls) {} +}; + +inline std::ostream& +operator<<(std::ostream& out, class_implicit_conversion_declaration const& x) +{ + out << tab(1) << "operator " << full_name(x._cls) << "() const;" << endl; + out << tab(1) << "operator " << full_name(x._cls) << "&();" << endl; + out << tab(1) << "operator " << full_name(x._cls) << " const&() const;" << endl; + return out << endl; +} + +struct class_implicit_conversion_definition +{ + eo_class const& _cls; + class_implicit_conversion_definition(eo_class const& cls) : _cls(cls) {} +}; + +inline std::ostream& +operator<<(std::ostream& out, class_implicit_conversion_definition const& x) +{ + out << "inline " << abstract_full_name(x._cls) << "::operator " + << full_name(x._cls) << "() const" << endl + << "{" << endl + << tab(1) << "return *static_cast<" << full_name(x._cls) + << " const*>(static_cast<void const*>(this));" << endl + << "}" << endl << endl; + + out << "inline " << abstract_full_name(x._cls) << "::operator " + << full_name(x._cls) << "&()" << endl + << "{" << endl + << tab(1) << "return *static_cast<" << full_name(x._cls) + << "*>(static_cast<void*>(this));" << endl + << "}" << endl << endl; + + out << "inline " << abstract_full_name(x._cls) << "::operator " + << full_name(x._cls) << " const&() const" << endl + << "{" << endl + << tab(1) << "return *static_cast<" << full_name(x._cls) + << " const*>(static_cast<void const*>(this));" << endl + << "}" << endl << endl; + + return out; +} + inline void eo_class_generator(std::ostream& out, eo_class const& cls) { - out << comment(cls.comment) + out << namespace_head(cls) + << "struct " << cls.name << ";" << endl << endl + << namespace_tail(cls) + << "namespace " << abstract_namespace << " {" << endl << endl + << namespace_head(cls) + << comment(cls.comment) << "struct " << cls.name << endl - << tab(2) << ": " << class_inheritance(cls) + << class_inheritance(cls) << '{' << endl << functors_constructor_methods(cls) - << functions_constructor_methods(cls) + << constructor_method_function_declarations(cls) + << function_declarations(cls) + << events(cls) + << eo_class_getter(cls) + << class_implicit_conversion_declaration(cls) + << "private:" << endl + << concrete_eo_ptr_getter(cls) + << "};" << endl << endl + << namespace_tail(cls) + << "}" << endl << endl + << namespace_head(cls) + << "struct " << cls.name << endl + << tab(2) << ": " << abstract_full_name(cls) << endl + << tab(2) << ", ::efl::eo::concrete" << endl + << '{' << endl << constructor_with_constructor_methods(cls) << constructor_eo(cls) << copy_constructor(cls) << destructor(cls) - << functions(cls.functions) - << events(cls) - << eo_class_getter(cls) << "private:" << endl << function_call_constructor_methods(cls) - << "};" << endl - << "static_assert(sizeof(" << cls.name << ") == sizeof(Eo*), \"sizeof(" << cls.name << ") != sizeof(Eo*)\");" << endl - << "static_assert(std::is_standard_layout<" << cls.name << ">::value, \"'" << cls.name << "' is not standard layout\");" - << endl << endl; + << "};" << endl << endl + << "static_assert(sizeof(" << full_name(cls) << ") == sizeof(Eo*), \"\");" << endl + << "static_assert(std::is_standard_layout<" << full_name(cls) << ">::value, \"\");" << endl + << endl + << namespace_tail(cls) + << constructor_method_function_definitions(cls) + << function_definitions(cls) + << class_implicit_conversion_definition(cls); } } } } // namespace efl { namespace eolian { namespace grammar { diff --git a/src/lib/eolian_cxx/grammar/eo_header_generator.hh b/src/lib/eolian_cxx/grammar/eo_header_generator.hh index 36ce432500..56f4e28f97 100644 --- a/src/lib/eolian_cxx/grammar/eo_header_generator.hh +++ b/src/lib/eolian_cxx/grammar/eo_header_generator.hh @@ -56,7 +56,7 @@ operator<<(std::ostream& out, include_dependencies const& x) it != last; ++it) for (auto it_p = (*it).params.begin(), last_p = (*it).params.end(); it_p != last_p; ++it_p) - for (eolian_type const& subtype : (*it_p).type) + for (eolian_type const& subtype : (*it_p).type.parts) for (std::string header : subtype.includes) headers.insert(header); @@ -64,7 +64,7 @@ operator<<(std::ostream& out, include_dependencies const& x) it != last; ++it) for (auto it_p = (*it).params.begin(), last_p = (*it).params.end(); it_p != last_p; ++it_p) - for (eolian_type const& subtype : (*it_p).type) + for (eolian_type const& subtype : (*it_p).type.parts) for (std::string header : subtype.includes) headers.insert(header); @@ -90,38 +90,6 @@ onceguard_tail(std::ostream& out, eo_class const& cls) } inline void -namespace_head(std::ostream& out, eo_class const& cls) -{ - if (cls.name_space != "") - { - std::string ns = cls.name_space; - size_t pos = 0; - while ((pos = ns.find("::")) != std::string::npos) - { - out << "namespace " << ns.substr(0, pos) << " { "; - ns.erase(0, pos+2); - } - out << "namespace " << ns << " {" << endl << endl; - } -} - -inline void -namespace_tail(std::ostream& out, eo_class const& cls) -{ - if (cls.name_space != "") - { - std::string ns = cls.name_space; - size_t pos = 0; - while ((pos = ns.find("::")) != std::string::npos) - { - out << "} "; - ns.erase(0, pos+2); - } - out << "} " << endl << endl; - } -} - -inline void include_headers(std::ostream& out, eo_class const& cls EINA_UNUSED, eo_generator_options const& opts) @@ -151,9 +119,7 @@ eo_header_generator(std::ostream& out, eo_class const& cls, eo_generator_options { onceguard_head(out, cls); include_headers(out, cls, opts); - namespace_head(out, cls); eo_class_generator(out, cls); - namespace_tail(out, cls); eo_inheritance_detail_generator(out, cls); onceguard_tail(out, cls); out << endl; diff --git a/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh b/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh index 31539c6ec2..9ed55d4302 100644 --- a/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh +++ b/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh @@ -66,8 +66,8 @@ inline std::ostream& operator<<(std::ostream& out, inheritance_operations_description const& x) { out << "template <typename T>" - << endl << "int initialize_operation_description(efl::eo::detail::tag<" - << x._cls.name_space << "::" << x._cls.name << ">" << endl + << endl << "int initialize_operation_description(::efl::eo::detail::tag<" + << full_name(x._cls) << ">" << endl << tab(11) << ", Eo_Op_Description* ops)" << endl << "{" << endl @@ -103,7 +103,7 @@ operator<<(std::ostream& out, inheritance_wrappers const& x) << _ns_as_prefix(x._cls) << "_" << x._cls.name << "_" << func.name << "_wrapper(Eo* objid EINA_UNUSED, " - << "efl::eo::detail::Inherit_Private_Data* self" + << "::efl::eo::detail::Inherit_Private_Data* self" << (func.params.size() ? ", " : "") << parameters_c_declaration(func.params) << ")" << endl @@ -122,7 +122,7 @@ operator<<(std::ostream& out, inheritance_wrappers const& x) << tab(2) << "}" << endl << tab(1) << "catch (...)" << endl << tab(2) << "{" << endl - << tab(3) << "eina_error_set( efl::eina::unknown_error() );" << endl + << tab(3) << "eina_error_set( ::efl::eina::unknown_error() );" << endl << tab(2) << "}" << endl; if (!function_is_void(func)) @@ -146,7 +146,7 @@ operator<<(std::ostream& out, inheritance_base_operations_size const& x) { out << "template<>" << endl << "struct operation_description_class_size< " - << x._cls.name_space << "::" << x._cls.name << " >" << endl + << full_name(x._cls) << " >" << endl << "{" << endl << tab(1) << "static const int value = " << x._cls.functions.size() @@ -209,7 +209,7 @@ operator<<(std::ostream& out, inheritance_base_operations const& x) { out << "template<>" << endl << "struct operations< " - << x._cls.name_space << "::" << x._cls.name << " >" << endl + << full_name(x._cls) << " >" << endl << "{" << endl << tab(1) << "template <typename T>" << endl << tab(1) << "struct type" << endl @@ -263,10 +263,10 @@ operator<<(std::ostream& out, inheritance_call_constructors const& x) eo_constructor const& ctor = *it; out << "inline void" << endl << "call_constructor(tag< " - << x._cls.name_space << "::" << x._cls.name << " >" << endl + << full_name(x._cls) << " >" << endl << tab(5) << ", Eo* eo, Eo_Class const* cls EINA_UNUSED," << endl << tab(5) << "args_class<" - << x._cls.name_space << "::" << x._cls.name + << full_name(x._cls) << ", ::std::tuple<" << parameters_types(ctor.params) << "> > const& args)" << endl @@ -281,11 +281,11 @@ operator<<(std::ostream& out, inheritance_call_constructors const& x) out << "inline void" << endl << "call_constructor(tag< " - << x._cls.name_space << "::" << x._cls.name << " >" << endl + << full_name(x._cls) << " >" << endl << tab(5) << ", Eo* eo, Eo_Class const* cls EINA_UNUSED," << endl << tab(5) << "args_class<" - << x._cls.name_space << "::" << x._cls.name - << ", ::std::tuple<efl::eo::parent_type> > const& args)" << endl + << full_name(x._cls) + << ", ::std::tuple<::efl::eo::parent_type> > const& args)" << endl << "{" << endl << tab(1) << "eo_do_super(eo, cls, ::eo_constructor());" << endl << tab(1) << "eo_do(eo, ::eo_parent_set(args.get<0>()._eo_raw));" << endl @@ -341,7 +341,7 @@ struct inheritance_extension inline std::ostream& operator<<(std::ostream& out, inheritance_extension const& x) { - std::string cls = x._cls.name_space + "::" + x._cls.name; + full_name const cls(x._cls); out << "template<>" << endl << "struct extension_inheritance< " << cls << ">" << endl @@ -381,7 +381,7 @@ inline std::ostream& operator<<(std::ostream& out, inheritance_eo_class_getter const& x) { out << "inline Eo_Class const* get_eo_class(tag<" - << x._cls.name_space << "::" << x._cls.name << ">)" << endl + << full_name(x._cls) << ">)" << endl << "{" << endl << tab(1) << "return (" << x._cls.eo_name << ");" << endl << "}" << endl << endl; diff --git a/src/lib/eolian_cxx/grammar/namespace_generator.hh b/src/lib/eolian_cxx/grammar/namespace_generator.hh new file mode 100644 index 0000000000..7f885ce6d4 --- /dev/null +++ b/src/lib/eolian_cxx/grammar/namespace_generator.hh @@ -0,0 +1,68 @@ + +#ifndef EOLIAN_CXX_NAMESPACE_GENERATOR_HH +#define EOLIAN_CXX_NAMESPACE_GENERATOR_HH + +#include "eo_types.hh" +#include "tab.hh" + +namespace efl { namespace eolian { namespace grammar { + +struct abstract_namespace_type {}; + +abstract_namespace_type const abstract_namespace = {}; + +inline std::ostream& +operator<<(std::ostream& out, abstract_namespace_type const&) +{ + return out << "eo_cxx"; +} + +struct namespace_head +{ + namespace_head(eo_class const& cls) : _cls(cls) {} + eo_class const& _cls; +}; + +inline std::ostream& +operator<<(std::ostream& out, namespace_head const& x) +{ + if (x._cls.name_space != "") + { + std::string ns = x._cls.name_space; + size_t pos = 0; + while ((pos = ns.find("::")) != std::string::npos) + { + out << "namespace " << ns.substr(0, pos) << " { "; + ns.erase(0, pos+2); + } + out << "namespace " << ns << " {" << endl << endl; + } + return out; +} + +struct namespace_tail +{ + namespace_tail(eo_class const& cls) : _cls(cls) {} + eo_class const& _cls; +}; + +inline std::ostream& +operator<<(std::ostream& out, namespace_tail const& x) +{ + if (x._cls.name_space != "") + { + std::string ns = x._cls.name_space; + size_t pos = 0; + while ((pos = ns.find("::")) != std::string::npos) + { + out << "} "; + ns.erase(0, pos+2); + } + out << "}" << endl << endl; + } + return out; +} + +} } } // namespace efl { namespace eolian { namespace grammar { + +#endif diff --git a/src/lib/eolian_cxx/grammar/parameters_generator.hh b/src/lib/eolian_cxx/grammar/parameters_generator.hh index f6084790bb..20f9e99c52 100644 --- a/src/lib/eolian_cxx/grammar/parameters_generator.hh +++ b/src/lib/eolian_cxx/grammar/parameters_generator.hh @@ -146,7 +146,7 @@ inline std::ostream& operator<<(std::ostream& out, callback_parameter_free_ev_add const& x) { out << "eo_do(" << x._eo_raw_expr - << ", eo_event_callback_add(EO_EV_DEL, &efl::eolian::free_callback_calback<" + << ", eo_event_callback_add(EO_EV_DEL, &::efl::eolian::free_callback_calback<" << parameter_no_ref_type(x._type, x._name) << ">, " << callback_tmp(x._name) << "));"; return out; diff --git a/src/lib/eolian_cxx/grammar/type_generator.hh b/src/lib/eolian_cxx/grammar/type_generator.hh index 94e91c088b..a476205271 100644 --- a/src/lib/eolian_cxx/grammar/type_generator.hh +++ b/src/lib/eolian_cxx/grammar/type_generator.hh @@ -6,11 +6,42 @@ #include <iosfwd> #include "eo_types.hh" +#include "namespace_generator.hh" namespace efl { namespace eolian { namespace grammar { using std::endl; +struct full_name +{ + eo_class const& _cls; + full_name(eo_class const& cls) : _cls(cls) {} +}; + +inline std::ostream& +operator<<(std::ostream& out, full_name const& x) +{ + if(!x._cls.name_space.empty()) + out << "::" << x._cls.name_space; + return out << "::" << x._cls.name; +} + +struct abstract_full_name +{ + eo_class const& _cls; + bool _from_golbal; + abstract_full_name(eo_class const& cls, bool from_golbal = true) + : _cls(cls), _from_golbal(from_golbal) {} +}; + +inline std::ostream& +operator<<(std::ostream& out, abstract_full_name const& x) +{ + if (x._from_golbal) + out << "::"; + return out << abstract_namespace << full_name(x._cls); +} + struct c_type { eolian_type_instance const& _list; @@ -24,7 +55,7 @@ operator<<(std::ostream& out, efl::eolian::grammar::c_type const& x) { assert(x._list.size() > 0); std::string res; - for (auto rit = x._list.rbegin(), last = x._list.rend(); rit != last; ++rit) + for (auto rit = x._list.parts.rbegin(), last = x._list.parts.rend(); rit != last; ++rit) { res = /*type_is_binding(*rit) ? (*rit).binding :*/ (*rit).native; } @@ -34,27 +65,31 @@ operator<<(std::ostream& out, efl::eolian::grammar::c_type const& x) struct reinterpret_type { - eolian_type_instance const& _list; - reinterpret_type(eolian_type_instance const& list) - : _list(list) + eolian_type_instance const& _type; + reinterpret_type(eolian_type_instance const& type) + : _type(type) {} }; inline std::ostream& operator<<(std::ostream& out, efl::eolian::grammar::reinterpret_type const& x) { - assert(x._list.size() > 0); + assert(x._type.size() > 0); std::string res; - for (auto rit = x._list.rbegin(), last = x._list.rend(); rit != last; ++rit) + for (auto rit = x._type.parts.rbegin(), last = x._type.parts.rend(); rit != last; ++rit) { eolian_type const& t = *rit; if (type_is_complex(t)) - res = t.binding + "< " + res + " >" + (t.is_out ? "*" : ""); + res = t.binding + "< " + res + " >"; else - res = type_is_binding(t) ? t.binding + (t.is_out ? "*" : "") + res = type_is_binding(t) ? t.binding : t.native; } assert(!res.empty()); + + if (x._type.is_out && type_is_binding(x._type.front())) + res += "*"; + return out << res; } @@ -70,9 +105,9 @@ inline std::ostream& operator<<(std::ostream& out, type_ownership const& x) { out << "std::tuple<"; - for (auto it=x._type.begin(), last=x._type.end(); it != last; ++it) + for (auto it=x._type.parts.begin(), last=x._type.parts.end(); it != last; ++it) { - if (it != x._type.begin()) + if (it != x._type.parts.begin()) out << ", "; out << ((*it).is_own ? "std::true_type" : "std::false_type"); } @@ -168,7 +203,7 @@ operator<<(std::ostream& out, to_cxx const& x) { if (type_is_binding(x._type)) { - out << "efl::eolian::to_cxx<" + out << "::efl::eolian::to_cxx<" << reinterpret_type(x._type) << ">(" << x._varname << ", " << type_ownership(x._type) << ")"; @@ -191,12 +226,12 @@ inline std::ostream& operator<<(std::ostream& out, to_c const& x) { if (type_is_callback(x._type)) - out << "efl::eolian::get_callback<" << type_to_native_str(x._type) + out << "::efl::eolian::get_callback<" << type_to_native_str(x._type) << ", " << parameter_no_ref_type(x._type, x._varname) << " >()"; else if (type_is_complex(x._type) && type_is_binding(x._type)) - out << "efl::eolian::to_native<" << c_type(x._type) << ">(" << x._varname << ")"; + out << "::efl::eolian::to_native<" << c_type(x._type) << ">(" << x._varname << ")"; else if (type_is_binding(x._type)) - out << "efl::eolian::to_c(" << x._varname << ")"; + out << "::efl::eolian::to_c(" << x._varname << ")"; else out << x._varname; return out; diff --git a/src/tests/eina_cxx/eina_cxx_test_accessor.cc b/src/tests/eina_cxx/eina_cxx_test_accessor.cc index bf7502ff9a..39b85f0ded 100644 --- a/src/tests/eina_cxx/eina_cxx_test_accessor.cc +++ b/src/tests/eina_cxx/eina_cxx_test_accessor.cc @@ -14,10 +14,10 @@ const Eo_Class *simple_class_get(void); #define MY_CLASS simple_class_get() -struct wrapper : efl::eo::base +struct wrapper : efl::eo::concrete { explicit wrapper(Eo* o) - : base(o) {} + : concrete(o) {} }; START_TEST(eina_cxx_accessor_indexing) diff --git a/src/tests/eina_cxx/eina_cxx_test_ptrarray.cc b/src/tests/eina_cxx/eina_cxx_test_ptrarray.cc index 5c41511b0d..67d472227e 100644 --- a/src/tests/eina_cxx/eina_cxx_test_ptrarray.cc +++ b/src/tests/eina_cxx/eina_cxx_test_ptrarray.cc @@ -15,10 +15,10 @@ const Eo_Class *simple_class_get(void); #define MY_CLASS simple_class_get() -struct wrapper : efl::eo::base +struct wrapper : efl::eo::concrete { explicit wrapper(Eo* o) - : base(o) {} + : concrete(o) {} }; START_TEST(eina_cxx_ptrarray_push_back) diff --git a/src/tests/eina_cxx/eina_cxx_test_ptrlist.cc b/src/tests/eina_cxx/eina_cxx_test_ptrlist.cc index 46378ee784..9e5fa2b2c1 100644 --- a/src/tests/eina_cxx/eina_cxx_test_ptrlist.cc +++ b/src/tests/eina_cxx/eina_cxx_test_ptrlist.cc @@ -47,10 +47,10 @@ static const Eo_Class_Description class_desc = { EO_DEFINE_CLASS(simple_class_get, &class_desc, EO_CLASS, NULL); -struct wrapper : efl::eo::base +struct wrapper : efl::eo::concrete { explicit wrapper(Eo* o) - : base(o) {} + : concrete(o) {} }; START_TEST(eina_cxx_ptrlist_push_back) diff --git a/src/tests/eolian_cxx/eolian_cxx_test_wrapper.cc b/src/tests/eolian_cxx/eolian_cxx_test_wrapper.cc index 123b508734..a2ab990bfd 100644 --- a/src/tests/eolian_cxx/eolian_cxx_test_wrapper.cc +++ b/src/tests/eolian_cxx/eolian_cxx_test_wrapper.cc @@ -16,7 +16,7 @@ START_TEST(eolian_cxx_test_wrapper_size) { efl::eo::eo_init init; - ::efl::eo::base b(nullptr); + ::efl::eo::concrete b(nullptr); ::callback c; fail_if(sizeof(b) != sizeof(Eo*)); |