2016-12-07 4 views
0

Я использую операторы enable_if для удаления возможных методов.Как enable_if используется для удаления кода

#include "gmpxx.h" 
#include <iostream> 

template <typename T> 
struct is_ring_field { 
}; 

template <> 
struct is_ring_field<int> { 
    static const bool value = false; 
}; 

template <> 
struct is_ring_field<mpq_class> { 
    static const bool value = true; 
}; 

template<typename T> 
std::enable_if<is_ring_field<T>::value,int> RankMat(T const& Input) 
{ 
    return 10; 
} 

template<typename T> 
std::enable_if<(not is_ring_field<T>::value),int> RankMat(T const& Input) 
{ 
    return 20; 
} 

int main() 
{ 
    int M1=10; 
    mpq_class M2=3; 
    std::cerr << "FICT rank(M1)=" << RankMat(M1) << "\n"; 
    std::cerr << "FICT rank(M2)=" << RankMat(M2) << "\n"; 
} 

Конечная цель - иметь методы, которые варьируются в зависимости от типа алгебраических данных на входе. По другим признакам это работало для меня, но не для этого. В этом случае компилятор странно говорит, что вызов неоднозначен, другими словами, не удалось выполнить std :: enable_if.

+1

Посмотрите на двух перегрузках для 'RankMat'. Какая часть перегрузок отличается? Может ли эта часть быть единственной частью функции, которая отличается допустимой перегрузкой? – NathanOliver

+2

Не забыли ли вы 'typename std :: enable_if <*,*> :: type'? –

+0

Да, я узнал после того, как написал свое сообщение, извините. Оба сообщения из clang ++ и g ++ были бесполезны. –

ответ

-1

Вы только что поместили его в неправильное положение. Попробуйте это:

template<typename T> 
int RankMat(T const& Input, typename std::enable_if<is_ring_field<T>::value,T>::type* = 0) 
{ 
     return 10; 
} 

template<typename T> 
int RankMat(T const& Input, typename std::enable_if<(not is_ring_field<T>::value),T>::type* = 0) 
{ 
     return 20; 
} 

или это:

template<typename T, typename TT = is_ring_field<T>> 
int RankMat(T const& Input) 
{ 
     return TT::value ? 10 : 20; 
} 
+0

На самом деле это не единственный контекст, позволяющий генерировать мягкую ошибку в sfinae ... см. [This] (http://melpon.org/wandbox/permlink/7MK1lLnULUVp04JY) и [this] (http://melpon.org/ wandbox/permlink/SlFEgbxo6ZzxDATO). Тот, который вы предложили, фактически доступен, так как C++ 11 до того, как параметры шаблона функции не были разрешены по умолчанию ... –

+0

Право. Быстрый ответ - плохая идея. Я дал неверную информацию. Это урок для меня. –

+0

Я не комментировал, чтобы дать вам урок, чтобы вы могли улучшить свой ответ ... –

2
std::enable_if<>

является допустимым типом; Вы должны использовать его type элемент для SFINAE:

template<typename T> 
typename std::enable_if<is_ring_field<T>::value,int>::type RankMat(T const& Input) 
{ 
    return 10; 
} 

template<typename T> 
typename std::enable_if<(not is_ring_field<T>::value),int>::type RankMat(T const& Input) 
{ 
    return 20; 
}