2016-01-03 3 views
3
constructor_caller<int,int,char*>(boxed_data); 

template<typename ... CONSTRUCTOR_PARAMETER_TYPES> 
static void constructor_caller(BoxedDataType & args) { 

    T * new_cpp_object = call_constructor_helper<CONSTRUCTOR_PARAMETER_TYPES...>(args, 
     std::index_sequence_for<CONSTRUCTOR_PARAMETER_TYPES...>()); 

} 

template <typename ...Fs, size_t...ns> 
static T * call_constructor_helper(BoxedDataType & args, std::index_sequence<ns...>){ 
    // args contains the boxed parameters and CastToNative unboxes 
    // the value to a native c++ type 
    return new T(CastToNative<Fs>()(args[ns])...); 
} 

У меня есть другое решение, которое включает в себя рекурсивное наследование на основе HEAD, TAIL ... типов параметров, но это даже больше, чем этот пример.Любой способ вызова конструктора (или любой функции/метода) из типов данных без прохождения двух шаблонных функций?

Кроме того, я думаю, чтобы обобщить это на работу для нормальных функций, методов объектов и конструкторов, мне понадобится 3 разных версии этого. Это верно?

+0

Для данного типа 'T' вы вызываете конструктор следующим образом:' T() 'или' T (args) 'или с символами скобок C++ 11,' T {} 'или' T {args } '. Это создает новый объект. Вы также можете вызвать конструктор, объявив переменную типа. –

+0

Вам необходимо как предоставить полный (но минимальный) пример, так и более четкое объяснение того, о чем идет речь. Проголосовал за то, чтобы закрыть как недостающий (соответствующий) пример. –

+0

Хм, думаю, вопрос довольно ясный. Там все в порядке и работает, за исключением BoxedDataType и CastToNative, но фактические типы не так интересны, как просто нужно работать, как в коде, который я поставил в вопросе. Я просто ищу способ не требовать второго вызова, который создает пакет параметров для index_sequence. – xaxxon

ответ

2

Вы делаете много вещей сразу.

типы Пасс в качестве значений:

template<class T>struct tag_t{constexpr tag_t(){}; using type=T;}; 
template<class T>constexpr tag_t<T> tag={}; 
template<class Tag>using type=typename Tag::type; 

Pass значения constexpr как типы:

template<std::size_t I> 
using index_t=std::integral_constant<std::size_t,I>; 
template<std::size_t I> 
constexpr index_t<I> index={}; 

Получить п-й ARG:

const auto get_nth_from=[](auto&& src){ 
    return [&src](auto index, auto tag)mutable->decltype(auto){ 
    using F=type<decltype(tag)>; 
    return CastToNative<F>()(src[index]); 
    }; 
}; 

template<class T> 
const auto construct=[](auto&&...args)->T*{ 
    return new T(decltype(args)(args)...); 
}; 

Теперь написать код работает на родовой объект функции цель.

namespace details { 
    template<class...Ts, std::size_t...Is, class F, class Get> 
    decltype(auto) call(std::index_sequence<Is...>, F&& f, Get&& get) { 
    return std::forward<F>(f)(get(index<Is>, tag<Ts>)...); 
    } 
} 
template<class...Ts, class F, class Get> 
decltype(auto) call(F&& f, Get&& get) { 
    return details::call<Ts...>(std::index_sequence_for<Ts>{}, std::forward<F>(f), std::forward<Get>(get)); 
} 

После всей этой работы, call_constructor выглядит следующим образом:

template<class T, class...Ts> 
T* call_constructor(BoxedDataType & args){ 
    return call<Ts...>(construct<T>, get_nth_from(args)); 
} 

или сконвертировано.

Одна цель, переданная call, создает T, другая вызывает метод, а другая - свободную функцию.

Одна вещь превращает список типов в индексы + типы, а затем вызывает функцию, которая становится одной операцией. Превращение индексов + типов в args другое. Превращение ctor в вызываемое другое. Каждый делает одно и делает это хорошо.

Больше на одну операцию, но меньше дублирования кода и новых операций легко.

Приведенное выше использует C++ 14 для краткости, а лямбды - как стиль.

Код не скомпилирован (записан на телефоне), поэтому обязательно содержит опечатки.

+0

Это займет некоторое время, чтобы переварить, но спасибо. – xaxxon

+0

@xaxxon Добавлена ​​грубая реализация. – Yakk

Смежные вопросы