2013-09-08 1 views
1

Я пишу библиотеку метапрограммирования, которая включает в себя набор типов и функций арифметики времени компиляции. Например:Отключение операторов перегрузки, если данный шаблон не является специализированным для параметров параметров оператора

metafunctions.hpp

template<typename T> 
struct function 
{ 
    using result = T; 
}; 

template<typename LHS , typename RHS> 
struct add_t; 

//Add metafunction 
template<typename LHS , typename RHS> 
using add = typename add_t<LHS,RHS>::result; 

fixed_point.hpp:

#include "metafunctions.hpp" 

template<long long int BITS , unsigned int PRECISSION> 
struct fixed_point 
{ 
    operator float() 
    { 
     return (float)BITS * std::pow(10.0f,-(float)PRECISION); //Its implemented as decimal fixed_point, not binary. 
    }; 
}; 

//An alias which provides a convenient way to create numbers: scientific notation 
template<int mantissa , int exponent = 0 , fbcount PRECISSION = mpl::DEFAULT_FRACTIONAL_PRECISION> // MANTISSA x 10^EXPONENT 
using decimal = mpl::fixed_point<decimal_shift<mantissa , PRECISSION + exponent>::value , PRECISSION>; 

//add specialization: 
template<long long int BITS1 , long long int BITS2 , unsigned int PRECISSION> 
struct add_t<mpl::fixed_point<BITS1,PRECISION> , mpl::fixed_point<BITS2,PRECISION>> : public mpl::function<fixed_point<BITS1+BITS2 , PRECISION>> {}; 

Несколько дней назад я заметил, что я мог бы воспользоваться decltype ключевого слова и реализации expression templates для упрощения синтаксиса сложных выражений:

expressions.hpp

template<typename LHS , typename RHS> 
mpl::add<LHS,RHS> operator+(const LHS& , const RHS&); 

template<typename LHS , typename RHS> 
mpl::sub<LHS,RHS> operator-(const LHS& , const RHS&); 

template<typename LHS , typename RHS> 
mpl::mul<LHS,RHS> operator*(const LHS& , const RHS&); 

template<typename LHS , typename RHS> 
mpl::div<LHS,RHS> operator/(const LHS& , const RHS&); 

Пример его использования:

using pi = mpl::decimal<3141592,-6>; //3141592x10⁻-6 (3,141592) 
using r = mpl::decimal<2,-2>; //0,002 
using a = mpl::decimal<1>; // 1,0 

using x = decltype(pi() * r() + (r()/a())); //pi*r + (r/a) 

Но это имеет и обратную сторону: Это перегружает определены для любого типа, поэтому выражения типа "a string" + "other string" припадков в expressions.hppoperator+ перегрузка. Конечно, разрешение перегрузки приводит к ошибке компиляции, поскольку компилятор пытается установить std::string как параметры типа mpl::add_t.

Мой вопрос: Есть ли способ отключить/включить перегруженные (с std::enable_if или что-то в этом роде), основанный на существовании специализации с определенного шаблона (mpl::add_t в примере) для параметров функций/операторы?.

Так что если тип результата выражения имеет специализацию для типов параметров, оператор будет включен и отключен в другом случае.

ответ

1

Нечто подобное может работать:

template<typename LHS , typename RHS> 
typename std::enable_if< 
    !std::is_same< 
     void, 
     typename mpl::add_t<LHS,RHS>::result 
    >::value, 
    mpl::add<LHS,RHS> 
>::type 
operator+(const LHS& , const RHS&) 
{ 
    // ... 
} 

опираясь на тот факт, что, если и только если существует специализация, ЬурейеЕ add_t<LHS,RHS>::result существует (и который не void).

+0

А как насчет того, чтобы использовать это с псевдонимом шаблона, 'mpl :: add = typename mpl :: add_t :: result', это сработает? Или компилятор отвергает его при создании псевдонима? – Manu343726

+0

@ Manu343726: Честно говоря, я не знаю. Попробуйте, у вас есть код, готовый проверить его :) –

+0

Хорошо, я попробую его позже. Даже если этот случай не работает, это выглядит как правильный ответ. Спасибо за вашу помощь. – Manu343726