
Hi Steven, I recently gave a presentation about type erasure in general, and your library in particular, at our local C++ UG (see here http://prezi.com/kg6d82f-_yky/type-erasure/ or the examples at https://github.com/CppUGBerlin/Talks/tree/master/2013_02_19_TypeErasure if you are interested). During the preparation I discovered some issues I'd like to ask you about. First I think I discovered a bug either in your lib or in clang(with libc++) when compiling one of the documentation examples in C++11 mode. #include <boost/type_erasure/any.hpp> #include <boost/type_erasure/any_cast.hpp> #include <boost/type_erasure/builtin.hpp> #include <boost/type_erasure/operators.hpp> #include <boost/type_erasure/tuple.hpp> #include <iostream> namespace bte = boost::type_erasure; namespace mpl = boost::mpl; int main() { typedef bte::any< mpl::vector< bte::copy_constructible<>, bte::typeid_<>, bte::addable<>, bte::ostreamable<> > > any_type; any_type x(10); any_type y(7); any_type z(x + y); std::cout << z << std::endl; } Compiling this in C++03 mode is fine, in C++11 mode it fails with this error: In file included from te_multi03.cpp:5: ../../Staging/type_erasure/boost/type_erasure/operators.hpp:187:1: error: no matching function for call to 'call' BOOST_TYPE_ERASURE_BINARY_OPERATOR(addable, +) see [1] below for full error. The next are some things which I didn't get to work, and the documentation is silent on any pitfalls. I tried to implement Sean Parent's example from his Value Semantics talk and failed to write a concept that calls free functions instead of members. Here is what I tried (full code and error at [2] below): template<class OBJ, class T> struct drawable { static void apply(const OBJ& obj, T& os, size_t pos) { draw(obj, os, pos); } }; I get an error like: error call to function 'draw' that is neither visible in the template definition nor found by argument-dependent lookup I worked around this problem by defining a concept map, but that is not realy a good solution. On researching a better solution I saw that you already added the convenience macros BOOST_TYPE_ERASURE_MEMBER and BOOST_TYPE_ERASURE_FREE, but didn't have much luck with them. Is there a compileable example where they are used somewhere? Best regards Fabio **** [1] *************************************************************** [1] full error docu example: In file included from te_multi03.cpp:5: ../../Staging/type_erasure/boost/type_erasure/operators.hpp:187:1: error: no matching function for call to 'call' BOOST_TYPE_ERASURE_BINARY_OPERATOR(addable, +) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../../Staging/type_erasure/boost/type_erasure/operators.hpp:166:20: note: expanded from macro 'BOOST_TYPE_ERASURE_BINARY_OPERATOR' return ::boost::type_erasure::call(name<T, U, R>(), lhs, rhs); \ ^~~~~~~~~~~~~~~~~~~~~~~~~~~ te_multi03.cpp:25:17: note: in instantiation of member function 'boost::type_erasure::operator+' requested here any_type z(x + y); ^ ../../Staging/type_erasure/boost/type_erasure/call.hpp:323:1: note: candidate template ignored: failed template argument deduction call( ^ ../../Staging/type_erasure/boost/type_erasure/call.hpp:356:1: note: candidate template ignored: substitution failure [with Op = boost::type_erasure::addable<boost::type_erasure::_self, boost::type_erasure::_self, boost::type_erasure::_self>, U = <const boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, boost::type_erasure::typeid_<boost::type_erasure::_self>, boost::type_erasure::addable<boost::type_erasure::_self, boost::type_erasure::_self, boost::type_erasure::_self>, boost::type_erasure::ostreamable<std::__1::basic_ostream<char>, boost::type_erasure::_self>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self>, boost::type_erasure::param<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, boost::type_erasure::typeid_<boost::type_erasure::_self>, boost::type_erasure::addable<boost::type_erasure::_self, boost::type_erasure::_self, boost::type_erasure::_self>, boost::type_erasure::ostreamable<std::__1::basic_ostream<char>, boost::type_erasure::_self>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, const boost::type_erasure::_self &>>]: no type named 'type' in 'boost::type_erasure::detail::call_result<boost::type_erasure::addable<boost::type_erasure::_self, boost::type_erasure::_self, boost::type_erasure::_self>, void (const boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, boost::type_erasure::typeid_<boost::type_erasure::_self>, boost::type_erasure::addable<boost::type_erasure::_self, boost::type_erasure::_self, boost::type_erasure::_self>, boost::type_erasure::ostreamable<std::__1::basic_ostream<char>, boost::type_erasure::_self>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self> &, boost::type_erasure::param<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, boost::type_erasure::typeid_<boost::type_erasure::_self>, boost::type_erasure::addable<boost::type_erasure::_self, boost::type_erasure::_self, boost::type_erasure::_self>, boost::type_erasure::ostreamable<std::__1::basic_ostream<char>, boost::type_erasure::_self>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, const boost::type_erasure::_self &> &), void>' call( ^ 1 error generated. **** [2] *************************************************************** [2] Code and error for Value semantic example: #include <boost/type_erasure/any.hpp> #include <boost/type_erasure/concept_interface.hpp> #include <boost/type_erasure/rebind_any.hpp> #include <boost/type_erasure/free.hpp> #include <vector> namespace bte = boost::type_erasure; namespace mpl = boost::mpl; //-------------------------------------------------------------------------------------------------- template<class OBJ, class T> struct drawable { static void apply(const OBJ& obj, T& os, size_t pos) { draw(obj, os, pos); } }; namespace boost { namespace type_erasure { template<class OBJ, class T, class Base> struct concept_interface< ::drawable<OBJ, T>, Base, OBJ> : Base { void draw(typename rebind_any<Base, T&>::type os, size_t pos) const { call(::drawable<OBJ, T>(), *this, os, pos); } }; } } using object_t = bte::any< mpl::vector< bte::copy_constructible<>, drawable<bte::_self, std::ostream> >>; //-------------------------------------------------------------------------------------------------- void draw(const int& value, std::ostream& out, size_t position) { out << std::string(position, ' ') << "int = " << value << std::endl; } void draw(const std::string& value, std::ostream& out, size_t position) { out << std::string(position, ' ') << "string = " << value << std::endl; } struct my_class_t {}; void draw(const my_class_t&, std::ostream& out, size_t position) { out << std::string(position, ' ') << "my_class_t" << std::endl; } //-------------------------------------------------------------------------------------------------- using document_t = std::vector<object_t>; // or std::vector<copy_on_write<object_t>>; void draw(const document_t& x, std::ostream& out, size_t position) { out << std::string(position, ' ') << "<document>" << std::endl; for (auto& e : x) { e.draw(out, position + 2); } out << std::string(position, ' ') << "</document>" << std::endl; } //-------------------------------------------------------------------------------------------------- using history_t = std::vector<document_t>; void commit(history_t& x) { assert(x.size()); x.push_back(x.back()); } void undo(history_t& x) { assert(x.size()); x.pop_back(); } document_t& current(history_t& x) { assert(x.size()); return x.back(); } //-------------------------------------------------------------------------------------------------- int main () { history_t h(1); current(h).emplace_back(0); current(h).emplace_back(std::string("Hello!")); draw(current(h), std::cout, 0); std::cout << "--------------------------" << std::endl; commit(h); current(h).emplace_back(current(h)); current(h).emplace_back(my_class_t()); draw(current(h), std::cout, 0); std::cout << "--------------------------" << std::endl; undo(h); draw(current(h), std::cout, 0); } **** Error: ************************************************************ te_sp_copy.cpp:14:59: error: call to function 'draw' that is neither visible in the template definition nor found by argument-dependent lookup static void apply(const OBJ& obj, T& os, size_t pos) { draw(obj, os, pos); } ^ ../../Staging/type_erasure/boost/type_erasure/detail/instantiate.hpp:91:28: note: in instantiation of member function 'drawable<int, std::__1::basic_ostream<char> >::apply' requested here BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_INSTANTIATE_IMPL, concept_sequence) ^ /usr/local/include/boost/preprocessor/repetition/repeat.hpp:38:60: note: expanded from macro 'BOOST_PP_REPEAT_1' # define BOOST_PP_REPEAT_1(c, m, d) BOOST_PP_REPEAT_1_I(c, m, d) ^ /usr/local/include/boost/preprocessor/repetition/repeat.hpp:43:63: note: expanded from macro 'BOOST_PP_REPEAT_1_I' # define BOOST_PP_REPEAT_1_I(c, m, d) BOOST_PP_REPEAT_1_ ## c(m, d) ^ /usr/local/include/boost/preprocessor/repetition/repeat.hpp:54:62: note: expanded from macro 'BOOST_PP_REPEAT_1_3' # define BOOST_PP_REPEAT_1_3(m, d) BOOST_PP_REPEAT_1_2(m, d) m(2, 2, d) ^ ../../Staging/type_erasure/boost/type_erasure/detail/instantiate.hpp:70:47: note: expanded from macro 'BOOST_TYPE_ERASURE_INSTANTIATE_IMPL' (void)&::boost::mpl::at_c<data, n>::type::apply; ^ ../../Staging/type_erasure/boost/type_erasure/any.hpp:182:13: note: in instantiation of function template specialization 'boost::type_erasure::detail::instantiate_concept3::apply<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::map1<boost::mpl::pair<boost::type_erasure::_self, int> > >' requested here BOOST_TYPE_ERASURE_INSTANTIATE1(Concept, T, U), ^ ../../Staging/type_erasure/boost/type_erasure/detail/instantiate.hpp:51:14: note: expanded from macro 'BOOST_TYPE_ERASURE_INSTANTIATE1' >::type::apply( \ ^ /usr/bin/../lib/c++/v1/memory:1681:31: note: in instantiation of function template specialization 'boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self>::any<int>' requested here ::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...); ^ /usr/bin/../lib/c++/v1/memory:1608:18: note: in instantiation of function template specialization 'std::__1::allocator<boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self>
::construct<boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self>, int>' requested here {__a.construct(__p, _VSTD::forward<_Args>(__args)...);} ^ /usr/bin/../lib/c++/v1/memory:1492:14: note: in instantiation of function template specialization
'std::__1::allocator_traits<std::__1::allocator<boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self> >
::__construct<boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self>, int>' requested here {__construct(__has_construct<allocator_type, pointer, _Args...>(), ^ /usr/bin/../lib/c++/v1/vector:1519:25: note: in instantiation of function template specialization
::construct<boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self>, int>' requested here __alloc_traits::construct(this->__alloc(), ^ te_sp_copy.cpp:71:15: note: in instantiation of function template specialization 'std::__1::vector<boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self>, std::__1::allocator<boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self> > >::emplace_back<int>' requested here current(h).emplace_back(0); ^ te_sp_copy.cpp:33:6: note: 'draw' should be declared prior to the call site void draw(const int& value, std::ostream& out, size_t position) { ^ te_sp_copy.cpp:14:59: error: call to function 'draw' that is neither visible in the template definition nor found by argument-dependent lookup static void apply(const OBJ& obj, T& os, size_t pos) { draw(obj, os,
'std::__1::allocator_traits<std::__1::allocator<boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self> > pos); } ^ ../../Staging/type_erasure/boost/type_erasure/detail/instantiate.hpp:91:28: note: in instantiation of member function 'drawable<std::__1::basic_string<char>, std::__1::basic_ostream<char>
::apply' requested here BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_INSTANTIATE_IMPL, concept_sequence) ^ /usr/local/include/boost/preprocessor/repetition/repeat.hpp:38:60: note: expanded from macro 'BOOST_PP_REPEAT_1' # define BOOST_PP_REPEAT_1(c, m, d) BOOST_PP_REPEAT_1_I(c, m, d) ^ /usr/local/include/boost/preprocessor/repetition/repeat.hpp:43:63: note: expanded from macro 'BOOST_PP_REPEAT_1_I' # define BOOST_PP_REPEAT_1_I(c, m, d) BOOST_PP_REPEAT_1_ ## c(m, d) ^ /usr/local/include/boost/preprocessor/repetition/repeat.hpp:54:62: note: expanded from macro 'BOOST_PP_REPEAT_1_3' # define BOOST_PP_REPEAT_1_3(m, d) BOOST_PP_REPEAT_1_2(m, d) m(2, 2, d) ^ ../../Staging/type_erasure/boost/type_erasure/detail/instantiate.hpp:70:47: note: expanded from macro 'BOOST_TYPE_ERASURE_INSTANTIATE_IMPL' (void)&::boost::mpl::at_c<data, n>::type::apply; ^ ../../Staging/type_erasure/boost/type_erasure/any.hpp:182:13: note: in instantiation of function template specialization
'boost::type_erasure::detail::instantiate_concept3::apply<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::map1<boost::mpl::pair<boost::type_erasure::_self, std::__1::basic_string<char> > > >' requested here BOOST_TYPE_ERASURE_INSTANTIATE1(Concept, T, U), ^ ../../Staging/type_erasure/boost/type_erasure/detail/instantiate.hpp:51:14: note: expanded from macro 'BOOST_TYPE_ERASURE_INSTANTIATE1' >::type::apply( \ ^ /usr/bin/../lib/c++/v1/memory:1681:31: note: in instantiation of function template specialization 'boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self>::any<std::__1::basic_string<char> >' requested here ::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...); ^ /usr/bin/../lib/c++/v1/memory:1608:18: note: in instantiation of function template specialization 'std::__1::allocator<boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self>
::construct<boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self>, std::__1::basic_string<char> >' requested here {__a.construct(__p, _VSTD::forward<_Args>(__args)...);} ^ /usr/bin/../lib/c++/v1/memory:1492:14: note: in instantiation of function template specialization
'std::__1::allocator_traits<std::__1::allocator<boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self> >
::__construct<boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self>, std::__1::basic_string<char> >' requested here {__construct(__has_construct<allocator_type, pointer, _Args...>(), ^ /usr/bin/../lib/c++/v1/vector:1519:25: note: in instantiation of function template specialization
'std::__1::allocator_traits<std::__1::allocator<boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self> >
::construct<boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self>, std::__1::basic_string<char> >' requested here __alloc_traits::construct(this->__alloc(), ^ te_sp_copy.cpp:72:15: note: in instantiation of function template specialization 'std::__1::vector<boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self>, std::__1::allocator<boost::type_erasure::any<boost::mpl::vector<boost::type_erasure::copy_constructible<boost::type_erasure::_self>, drawable<boost::type_erasure::_self, std::__1::basic_ostream<char> >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::type_erasure::_self> > ::emplace_back<std::__1::basic_string<char> >' requested here current(h).emplace_back(std::string("Hello!")); ^ te_sp_copy.cpp:37:6: note: 'draw' should be declared prior to the call site void draw(const std::string& value, std::ostream& out, size_t position) { ^ 2 errors generated.

AMDG On 02/25/2013 08:45 AM, Fabio Fracassi wrote:
Hi Steven,
I recently gave a presentation about type erasure in general, and your library in particular, at our local C++ UG (see here http://prezi.com/kg6d82f-_yky/type-erasure/ or the examples at https://github.com/CppUGBerlin/Talks/tree/master/2013_02_19_TypeErasure if you are interested). During the preparation I discovered some issues I'd like to ask you about.
First I think I discovered a bug either in your lib or in clang(with libc++) when compiling one of the documentation examples in C++11 mode.
I haven't tested much with clang in C++11 mode. I wasn't able to get libc++ working on Linux. Are you using the latest version: r83101? Also, exactly what version of clang are you using? I'll take a look at this later today.
<snip>
The next are some things which I didn't get to work, and the documentation is silent on any pitfalls.
I tried to implement Sean Parent's example from his Value Semantics talk and failed to write a concept that calls free functions instead of members. Here is what I tried (full code and error at [2] below):
template<class OBJ, class T> struct drawable { static void apply(const OBJ& obj, T& os, size_t pos) { draw(obj, os, pos); } };
I get an error like: error call to function 'draw' that is neither visible in the template definition nor found by argument-dependent lookup
I worked around this problem by defining a concept map, but that is not realy a good solution.
The problem is the way name lookup works. It's clear that draw can't be found in the template definition, since it isn't declared until later on. Argument dependent lookup usually works, but in this case, the only associated namespace is std (from std::ostream) and draw is defined in the global namespace. (Note that the built-in types have no associated namespaces). BOOST_TYPE_ERASURE_FREE will have exactly the same problem. The solution is add declarations of draw for all builtin types /before/ the definition of drawable.
On researching a better solution I saw that you already added the convenience macros BOOST_TYPE_ERASURE_MEMBER and BOOST_TYPE_ERASURE_FREE, but didn't have much luck with them. Is there a compileable example where they are used somewhere?
libs/type_erasure/example/basic.cpp uses both. See also libs/type_erasure/test/member.cpp and libs/type_erasure/test/free.cpp. In Christ, Steven Watanabe

On 2/25/13 6:13 PM, Steven Watanabe wrote:
AMDG
[snip]
First I think I discovered a bug either in your lib or in clang(with libc++) when compiling one of the documentation examples in C++11 mode.
I haven't tested much with clang in C++11 mode. I wasn't able to get libc++ working on Linux. Are you using the latest version: r83101? Also, exactly what version of clang are you using? I'll take a look at this later today.
Just updated to revision 83153 (boost sandbox), The problem remains. I am using Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) Target: x86_64-apple-darwin12.2.0 Thread model: posix (the one which comes with XCode 4.6) If you like I can send you the output of running your test suite. [snip]
The problem is the way name lookup works. It's clear that draw can't be found in the template definition, since it isn't declared until later on. Argument dependent lookup usually works, but in this case, the only associated namespace is std (from std::ostream) and draw is defined in the global namespace. (Note that the built-in types have no associated namespaces). BOOST_TYPE_ERASURE_FREE will have exactly the same problem. The solution is add declarations of draw for all builtin types /before/ the definition of drawable.
Ok, this works, but makes it impossible to (reliably) define the concept in isolation. Quite a severe limitation. Is there any possibility to overcome this?
On researching a better solution I saw that you already added the convenience macros BOOST_TYPE_ERASURE_MEMBER and BOOST_TYPE_ERASURE_FREE, but didn't have much luck with them. Is there a compileable example where they are used somewhere?
libs/type_erasure/example/basic.cpp uses both. See also libs/type_erasure/test/member.cpp and libs/type_erasure/test/free.cpp.
I see. This seems to be another problem which has to do with the C++11 mode. Best regards Fabio

AMDG On 02/25/2013 11:30 AM, Fabio Fracassi wrote:
On 2/25/13 6:13 PM, Steven Watanabe wrote: [snip]
First I think I discovered a bug either in your lib or in clang(with libc++) when compiling one of the documentation examples in C++11 mode.
I haven't tested much with clang in C++11 mode. I wasn't able to get libc++ working on Linux. Are you using the latest version: r83101? Also, exactly what version of clang are you using? I'll take a look at this later today.
Just updated to revision 83153 (boost sandbox), The problem remains. I am using Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) <snip>
I've just committed a fix for this. I just forgot to handle a case inside one clang #ifdef branch.
[snip]
The problem is the way name lookup works. It's clear that draw can't be found in the template definition, since it isn't declared until later on. Argument dependent lookup usually works, but in this case, the only associated namespace is std (from std::ostream) and draw is defined in the global namespace. (Note that the built-in types have no associated namespaces). BOOST_TYPE_ERASURE_FREE will have exactly the same problem. The solution is add declarations of draw for all builtin types /before/ the definition of drawable.
Ok, this works, but makes it impossible to (reliably) define the concept in isolation. Quite a severe limitation. Is there any possibility to overcome this?
This isn't as bad as you might think. It only applies to built in arithmetic types and types in the standard library of which there are a known fixed set. In Christ, Steven Watanabe
participants (2)
-
Fabio Fracassi
-
Steven Watanabe