2010-11-17 3 views
0

У меня есть следующий код в классеКомпилятор не может вывести специализированный шаблон в C++

struct ConstrType{}; 
    struct ConstrType3{}; 
    struct ConstrType2{}; 
    struct ConstrType1{}; 

    template<typename InType, typename OutType, typename ConstrType> 
    class getInterestRateIndex_impl{ 
    public: 
    getInterestRateIndex_impl(){ 
     std::cout << "Generic getInterestedRateIndex_impl instantiated. Failed" << std::endl; 
//  BOOST_STATIC_ASSERT(sizeof(ConstrType) == 0); 
    } 
    boost::shared_ptr<OutType> operator()() const{ 
     return boost::shared_ptr<OutType>(); 
    } 
    }; 


    template<typename InType, typename OutType> 
    class getInterestRateIndex_impl<InType, OutType, ConstrType2>{ 
    public: 
    getInterestRateIndex_impl(){ 
     std::cout << "ConstrType2 getInterestedRateIndex_impl instantiated." << std::endl; 
    } 
    boost::shared_ptr<OutType> operator()() const{ 
     return boost::shared_ptr<OutType>(); 
    } 
    }; 


    template<typename InType, typename OutType> 
    class getInterestRateIndex_impl<InType, OutType, ConstrType1>{ 
    public: 
    getInterestRateIndex_impl(){ 
     std::cout << "ConstrType1 getInterestedRateIndex_impl instantiated." << std::endl; 
    } 
    boost::shared_ptr<OutType> operator()() const{ 
     return boost::shared_ptr<OutType>(); 
    } 
    }; 



    template<typename InType, typename OutType> 
    boost::shared_ptr<OutType> getInterestRateIndex() const{ 
// BOOST_STATIC_ASSERT(boost::is_base_of<OutType, InType>::value); 

    typedef typename 
     boost::mpl::if_ 
     < 
      boost::is_same<InType, QuantLib::Libor>, 
      QuantLib::Libor, 
      boost::mpl::if_ 
      < 
       boost::mpl::or_ 
       < 
        boost::mpl::or_ 
        < 
         boost::is_same<InType, QuantLib::Euribor>, 
         boost::is_same<InType, QuantLib::EURLibor>, 
         boost::is_base_of<QuantLib::Libor, InType> 
        > 
       >, 
       ConstrType2, 
       boost::mpl::if_ 
       < 
        boost::mpl::or_ 
        < 
         boost::is_base_of<QuantLib::Euribor, InType>, 
         boost::is_base_of<QuantLib::EURLibor, InType> 
        >, 
        ConstrType1, 
        ConstrType 
       > 
      > 
     >::type Type; 
// std::cout << typeid(Type).name() << std::endl; 
// throw std::exception(typeid(Type).name()); 

    return getInterestRateIndex_impl<InType, OutType, Type>()(); 

    } 

Когда я создаю экземпляр класса и вызывать getInterestRateIndex<DerivedFromLiborType, BaseType>(), компилятор не может выбрать специализацию. Когда я раскомментирую линию exception, он может хотя обнаружить, что Type после typedef - ConstrType2. Я пропустил что-нибудь, что может намекнуть компилятору на выбор правильной специализации?

PS: логика шаблона предполагают, чтобы сделать что-то вроде .....

if(T is Libor) 
    return LiborType 
if(
    or(
     or(T = Euribor, 
     T = EURLibor), 
     is_base_of(T, Libor) 
    ), 
    ConstrType2, 
    if( 
     or(is_base_of(T, Euribor), 
      is_base_of(T, EURLibor)), 
     ConstrType1, 
     ConstrType 
    ) 
    ) 

Я делаю это потому, что мне нужно послать shared_ptr в зависимости от типа входного сигнала, и требуемый базовый тип в shared_ptr обертке ,

+0

ли компилятор излучающий ошибку? или это просто выбор неправильной специализации? – zdan

+0

@zdan. MSVC компилирует его и выбирает класс шаблона по умолчанию. – leon

+1

Глаза кровотечения. Можете ли вы кипятить это немного? –

ответ

0

Проблема заключается в том, что внешняя, если оператор не может вывести тип «затем» ветви и возвращают усугубляются тип наддува структур и, следовательно, всегда выбирая полный шаблон неспециализированных

1

Во-первых, что сказал Джон Диблинг в комментарии: попробуйте немного сварить это. Что было бы идеальным, это увидеть что-то, что делает работать рядом с чем-то похожим, что не.

Просто предположите, но, сравнивая с тем, что вы собираетесь делать с помощью своего псевдокода, похоже, что вы перепутали несколько звонков boost::mpl::or_. Может быть,

  boost::mpl::or_ 
      < 
       boost::mpl::or_ 
       < 
        boost::is_same<InType, QuantLib::Euribor>, 
        boost::is_same<InType, QuantLib::EURLibor>, 
        boost::is_base_of<QuantLib::Libor, InType> 
       > 
      >, 

должен быть

  boost::mpl::or_ 
      < 
       boost::mpl::or_ 
       < 
        boost::is_same<InType, QuantLib::Euribor>, 
        boost::is_same<InType, QuantLib::EURLibor> 
       >, 
       boost::is_base_of<QuantLib::Libor, InType> 
      >, 

В настоящее время у вас есть то, что выглядит как 1 1-операнда or_ и 1 3-операнда or_. Согласно Boost MPL docs, or_ требует не менее 2 операндов, поэтому, возможно, ваш 1-операнд or_, который я использую для вызова неопределенного поведения, разрушает вещи. (Я удивлен, что он компилируется.)

+0

Хорошая добыча, но это не проблема :( – leon

0

Сначала вы определили struct ConstrType{}; , а затем вы повторно используете ConstrType в качестве параметра шаблона здесь template<typename InType, typename OutType, typename ConstrType> class getInterestRateIndex_impl{ ?? ... Это требует неприятностей. Я бы переименовал одну из них.