0

based on this question and the answer provided by "Dave", how to specialize the case for handling the non-integral types to handle a type say QDate (used in Qt for handling date related tasks)?

The function I want to specialize is:

void extract(const std::string str)
{
        std::bitset<sizeof(T) * CHAR_BIT> bs(str.substr(m_start, m_len));
        m_data = static_cast<T>(bs.to_ulong());
}

an std::string of 1s and 0s is supplied to this function and then based on an start and length I need to convert it to the type the template class containing this function was instantiated with. It doesn't make sense when the type is not integral or can't be produced using the std::bitset.

Community
  • 1
  • 1
max
  • 2,627
  • 1
  • 24
  • 44
  • Can you show an example of the function you want to have custom behavior for `QDate`? Depending on that, there might be no need for SFINAE, an overload might suffice. – Praetorian Jan 17 '15 at 23:54
  • @Praetorian I've added the function. – max Jan 18 '15 at 00:04
  • You should take the `str` argument by `const&`, not just `const`, to avoid unnecessary copying. – Praetorian Jan 18 '15 at 00:49
  • I've rolled back the question. It's in bad taste to accept a correct answer and then modify the question to made that answer *no longer correct*. – Drew Dormann Jan 18 '15 at 02:21
  • @DrewDormann I didn't mean to do that. I wanted to see if I have understood the point of the answer correctly. – max Jan 18 '15 at 10:36

1 Answers1

1

I'm not sure I understand your use case completely, but I think it's something similar to this

template<typename T>
struct foo
{
    T m_data;
    // others ...

    void extract(const std::string str)
    {
        std::bitset<sizeof(T) * CHAR_BIT> bs(str.substr(m_start, m_len));
        m_data = static_cast<T>(bs.to_ulong());
    }
};

But you want extract to do something different when foo is instantiated with QDate. There are a few different ways to get this done, SFINAE being one of them.

But you can't simply tack on an enable_if expression to extract because for SFINAE to work the substitution failure needs to happen in the immediate context, and T is known by the time foo<T>::extract is instantiated. So add a dummy template parameter to extract that defaults to T.

template<typename U=T>
typename std::enable_if<std::is_same<U, QDate>::value>::type
    extract(const std::string str)
{
  // this will be used when T=QDate
}


template<typename U=T>
typename std::enable_if<!std::is_same<U, QDate>::value>::type
    extract(const std::string str)
{
  // this will be used when T!=QDate
}

If extract is the only thing that changes behavior then another way to accomplish this would be to move all common functionality to another class which foo would inherit from.

template<typename T> 
struct foo_base
{
  // common functionality
};

template<typename T>
struct foo : foo_base<T>
{
  void extract(const std::string str)
  {
    std::bitset<sizeof(T) * CHAR_BIT> bs(str.substr(m_start, m_len));
    m_data = static_cast<T>(bs.to_ulong());
  }
};

// Specialization for QDate
template<>
struct foo<QDate> : foo_base<QDate>
{
  void extract(const std::string str)
  {
    // QDate specific functionality
  }
};
Praetorian
  • 106,671
  • 19
  • 240
  • 328
  • @Baracuda Hi, since you selected the answer, I'm guessing you solved the problem? – Praetorian Jan 18 '15 at 06:14
  • yes the problem is solved but I'm not sure about it's technical correctness the way I did it. I made an edit to the question but Drew Dormann rolled it back saying I tried to made your answer look incorrect. – max Jan 18 '15 at 10:40