Boost.Type_erasure: функция-член возвращает _self

Я хочу использовать Boost.Type_erasure для функции-члена, которая возвращает сам тип. С _self как тип возврата, все в порядке. Тем не менее, когда тип возврата изменения в pair<_self, some_type>возникает ошибка. Следующий код воспроизводит проблему.

#include <utility>
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/member.hpp>

BOOST_TYPE_ERASURE_MEMBER((HasTest1), Test1, 0)
BOOST_TYPE_ERASURE_MEMBER((HasTest2), Test2, 0)

using boost::type_erasure::_self;
using std::pair;
using Type1 = boost::type_erasure::any<
boost::mpl::vector<
boost::type_erasure::copy_constructible<>,
HasTest1<_self(), _self const>
>,
_self
>;
using Type2 = boost::type_erasure::any<
boost::mpl::vector<
boost::type_erasure::copy_constructible<>,
HasTest2<pair<_self, int>(), _self const>
>,
_self
>;

int main() {
struct test {
test Test1() const { throw; }
pair<test, int> Test2() const { throw; }
};

Type1{ test{} };// OK
Type2{ test{} };// Error
// Type2{ test{} }.Test2().first.Test2();// Expected to work
}

Как я могу исправить эту проблему без использования возвращаемых аргументов?

Пример сообщения об ошибке:

main.cpp:6:1: error: no viable conversion from 'pair<test, [...]>' to 'pair<boost::type_erasure::_self, [...]>'

BOOST_TYPE_ERASURE_MEMBER((HasTest2), Test2, 0)

^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

0

Решение

Ниже приводится ответ Стивена Ватанабе.

Библиотека может обрабатывать только заполнители на верхнем уровне. Там нет никакого способа справиться с общим делом, X<_self> автоматически. По сути, это то же самое, что ковариантные типы возврата для виртуальных функций, которые имеют аналогичные ограничения.

Чтобы получить желаемый эффект, вам нужно определить concept_interface вручную.

В качестве альтернативы я использую boost::any обойти.

#include <utility>
#include <boost/any.hpp>
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/member.hpp>

BOOST_TYPE_ERASURE_MEMBER((HasTest), Test, 0)

using Type = boost::type_erasure::any<
boost::mpl::vector<
boost::type_erasure::copy_constructible<>,
HasTest<boost::any()>
>
>;

int main() {
struct TestType {
auto Test() {
return std::make_pair(0, Type{ *this });
}
};
auto obj = Type{ TestType{} }.Test();
boost::any_cast<std::pair<int, Type>&>(obj).second.Test();
}
0

Другие решения

Других решений пока нет …