开发者

Compiler cannot deduce the specialised template in C++

I have the following code in a class

  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 instant开发者_运维问答iated." << 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>()( );

  }

When I instantiate the class and invoke getInterestRateIndex<DerivedFromLiborType, BaseType>(), the compiler cannot choose the specialisation. When I uncomment the exception line, it can though detect that the Type after typedef is ConstrType2. Am I missing anything that can hint the compiler to choose the right specialisation?

PS: the template logic suppose to do something like .....

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
      )
   )

I do this because I need to dispatch shared_ptr based on the input type, and the desired underlying type in the shared_ptr wrapper.


First, what John Dibling said in a comment: please try to boil this down a bit. What would be ideal is to see something that does work alongside something similar that doesn't.

Just a guess, but by comparing with what you are intending to do via your pseudocode, it looks like you have messed up a couple of boost::mpl::or_ calls. Maybe

          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>
              >
          >,

should be

          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>
          >,

At present you have what looks like 1 1-operand or_ and 1 3-operand or_. According to the Boost MPL docs, or_ requires at least 2 operands, so perhaps your 1-operand or_, which I take to invoke Undefined Behaviour, is wrecking things. (I'm surprised it compiles.)


You first define struct ConstrType{}; and then you reuse ConstrType as a template parameter here template<typename InType, typename OutType, typename ConstrType> class getInterestRateIndex_impl{ ?? ... That's asking for trouble. I'd rename one of them.


The problem is that the outer if statement cannot deduce the type of the "then" branch and return a compounded type of boost structs and therefore always choosing the full unspecialised template

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜