2015-09-09 2 views
0

Я работаю с картой функций для простого языка, который я разрабатываю, все работает отлично, но я хотел бы предоставить лучший способ определить числовые операторы, которые работают с численными значениями в более сжатой форме.Использование аргументов шаблона внутри lambda

Основная проблема заключается в том, что у меня есть что-то вроде:

using BinaryFunction = std::function<StackValue(StackValue,StackValue)>; 

registerFunction("+", Type::FLOAT, {Type::FLOAT, Type::FLOAT}, BinaryFunction([](StackValue v1, StackValue v2) { return StackValue(v1.as<float>() + v2.as<float>()); })); 
registerFunction("+", Type::FLOAT, {Type::FLOAT, Type::INT}, BinaryFunction([](StackValue v1, StackValue v2) { return StackValue(v1.as<float>() + v2.as<s32>()); })); 
.. 

Так в основном для каждого оператора, который поддерживает как float и int типов данных я должен предоставить 4 функцию, которая работает с возможными комбинациями

int, int -> int 
int, float -> float 
float, int -> float 
float, float -> float 

Теперь я не хочу предоставлять неявное преобразование типов, поэтому я в порядке с 4 различными функциями для каждой комбинации, но мне хотелось бы определить их все сразу, не повторяя код ,

Проблема заключается в том, как я мог сделать это, главная проблема заключается в лямбда:

[](StackValue v1, StackValue v2) { return StackValue(v1.as<float>() + v2.as<float>()); }; 

Чтобы быть в состоянии делать то, что мне нужно, я бы нужен способ Параметризуем кода с шаблоном, что-то вроде

return StackValue(v1.as<T1>() + v2.as<T2>()) 

Тогда правильная специализация StackValue<T>(T) берет на себя все остальное.

, так что я могу после этого сделать что-то вроде

registerNumericFunction(...) 
{ 
    registerTemplate<float, float>(...); 
    registerTemplate<s32, float>(...); 
    .. 
} 

Но я не найти умный способ сделать это, потому что мне нужно передать лямбда-методу, который должен быть параметрическим. Я не знаю, возможно ли вообще.

+0

Что такое 'Тип'? – CoffeeandCode

+0

@CoffeeandCode: 'enum Тип: u8', это не проблема, так как я могу использовать' std :: условный', чтобы выбрать правильный в соответствии с двумя типами операторов. – Jack

ответ

2

Вы имеете в виду что-то вроде этого?

template <typename T1, typename T2> 
void registerTemplate() { 
    registerFunction("+", Type::FLOAT, {Type::FLOAT, Type::FLOAT}, 
        BinaryFunction([](StackValue v1, StackValue v2) { 
         return StackValue(v1.as<T1>() + v2.as<T2>()); 
        })); 
} 

registerTemplate<float, float>(); 
registerTemplate<s32, float>(); 

Или это?

template <typename T1, typename T2, typename Op> 
BinaryFunction makeFunction(Op op) { 
    return [op](StackValue v1, StackValue v2) { 
     return StackValue(op(v1.as<T1>(), v1.as<T2>())); 
    }; 
} 

Для использования в качестве:

registerFunction("+", ..., makeFunction<float, float>(std::plus<>{})); 
registerFunction("+", ..., makeFunction<s32, float>(std::plus<>{})); 

Было бы очень полезно, если вы на самом деле сделать это ясно в вашем вопросе, что именно вы хотели достичь.

+0

Это параметризует тип определенного лямбда, который не то, что я ищу, а не общий лямбда. Проблема в том, что у меня много операторов (+, -, *, /, <, >, <=, == и т. Д.), И я хотел бы зарегистрировать каждый оператор один раз, но неявно определить его для всех комбинаций. В основном что-то вроде 'registerTemplate ' – Jack

+0

@Jack Итак, передайте как 'std :: plus <>' в качестве другого аргумента. Я действительно не понимаю, о чем вы спрашиваете. – Barry

+0

Действительно, я не знал о 'std :: plus <>' и о существовании его друзей, это определенно решает проблему. – Jack

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