10

I have a template that needs to work with the next types: int, float, double, std::chrono::nanoseconds, std::chrono::milliseconds and std::chrono::seconds.

The template has a member function to work with int, float and double but I need to write one specialization for nanoseconds, another for milliseconds and another for seconds.

To get a working code I'm forced to write one specialization for every std::chrono "type" with basically the same code. So I'm loosing the advantages of using templates.

I have read that the chrono "types" are typedefs of an instantiation of duration.

Is there a way to write only one specialization for nanoseconds, milliseconds and seconds?

Here is how my code looks like:

// file: myclass.hh

template<typename T> 
class Myclass {
public:
    // Variable (I want to initialize m_max to the maximum value possible for the 
    // T type)
    T m_max ;

    // Constructor
    Myclass ( ) ;
};

// file: myclass.cc

#include <limits>
#include <chrono>

// Constructor for int, float, double, etc...
template<typename T> 
Myclass<T>::Myclass ( ) :
    // Here we are setting m_max to the maximum value
    m_max( std::numeric_limits<T>::max( ) )
{}

// Constructor: Specialization number 1 for std::chrono::nanoseconds
template<> 
Myclass<std::chrono::nanoseconds>::Myclass()  :
    // Here we are setting m_max to the maximum value
    m_max( std::chrono::nanoseconds::max( ) )
{}

// Constructor: Specialization number 2 for std::chrono::milliseconds
template<> 
Myclass<std::chrono::milliseconds>::Myclass ( ) :
    // Here we are setting m_max to the maximum value
    m_max( std::chrono::milliseconds::max() )
{}

// Constructor: Specialization number 3 for std::chrono::seconds
template<> 
Myclass<std::chrono::seconds>::Myclass ( ) :
    // Here we are setting m_max to the maximum value
    m_max( std::chrono::seconds::max( ) )
{}

// Forcing instantiations
template class Myclass<int>;
template class Myclass<float>;
template class Myclass<double>;

template class Myclass<std::chrono::nanoseconds>;
template class Myclass<std::chrono::milliseconds>;
template class Myclass<std::chrono::seconds>;

// file: main.cc

#include <iostream>

int main() {
    Myclass<int>                       intobj;
    Myclass<float>                     floatobj;
    Myclass<double>                    doubleobj;
    Myclass<std::chrono::nanoseconds>  nanosecondseobj;
    Myclass<std::chrono::milliseconds> millisecondseobj;
    Myclass<std::chrono::seconds>      secondseobj;

    using std::cout;
    using std::endl;
    cout << "Maximum value for int = "          << intobj.m_max << endl;
    cout << "Maximum value for float = "        << floatobj.m_max << endl;
    cout << "Maximum value for double = "       << doubleobj.m_max << endl;
    cout << "Maximum value for nanoseconds = "  << nanosecondseobj.m_max.count( ) << endl;
    cout << "Maximum value for milliseconds = " << millisecondseobj.m_max.count( ) << endl;
    cout << "Maximum value for seconds = "      << secondseobj.m_max.count( ) << endl;
    return 0;
}
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
ClK
  • 105
  • 7
  • "*I have a template that needs to work with the next types:*" Why? Why would you have a template that can work with `nanoseconds` and `milliseconds`, but not *`microseconds`*? This would make for a *terrible* interface. Indeed, the *whole point* of the `duration` interface is to allow interoperation between the units used by two different users. If you provide a function that takes time, it should be able to work just fine if I pass it `microseconds` or `nanoseconds`. – Nicol Bolas Apr 08 '18 at 17:42
  • Also, answers do not go in the *question*; they go in the answer section. – Nicol Bolas Apr 08 '18 at 17:43
  • @NicolBolas If you read the question carefully you will notice that the question is: "In a template is there a way to write only one specialization for **every** chrono instantiation? (nanoseconds, milliseconds, seconds, etc)" The example code that I posted was only for clarifying my question and for learning purposes. – ClK Apr 09 '18 at 19:43
  • @NicolBolas Moved "Complete usage demonstration" to aswer section – ClK Apr 09 '18 at 19:44

2 Answers2

14

You can make a partial specialization for std::chrono::duration

template<typename T, typename Ratio> 
class Myclass<std::chrono::duration<T,Ratio> > {
public:
  // Variable (I want to initialize m_max to the maximum value possible for the 
  // T type)
  std::chrono::duration<T,Ratio> m_max ;

  // Constructor
  Myclass ( ) : m_max(std::chrono::duration<T,Ratio>::max()) {}
};

Usage demonstration: https://wandbox.org/permlink/Q8R5pz2UPawnZ1NG

chtz
  • 17,329
  • 4
  • 26
  • 56
  • Thanks a lot for your fast answer!. I will copy your usage demonstration example for future readings. – ClK Apr 08 '18 at 15:55
0

Complete usage demonstration posted by: chtz

#include <iostream>
#include <limits>
#include <chrono>

template<typename T> 
class Myclass {
public:
  // Variable (I want to initialize m_max to the maximum value possible for the 
  // T type)
  T m_max ;

  // Constructor
  Myclass ( ) : m_max(std::numeric_limits<T>::max()) {}
};

template<typename T, typename Ratio> 
class Myclass<std::chrono::duration<T,Ratio> > {
public:
  // Variable (I want to initialize m_max to the maximum value possible for the 
  // T type)
  std::chrono::duration<T,Ratio> m_max ;

  // Constructor
  Myclass ( ) : m_max(std::chrono::duration<T,Ratio>::max()) {}
};

int main() {
    Myclass<int>                       intobj;
    Myclass<float>                     floatobj;
    Myclass<double>                    doubleobj;
    Myclass<std::chrono::nanoseconds>  nanosecondseobj;
    Myclass<std::chrono::milliseconds> millisecondseobj;
    Myclass<std::chrono::seconds>      secondseobj;

    using namespace std;
    cout << "Maximum value for int = "          << intobj.m_max << endl;
    cout << "Maximum value for float = "        << floatobj.m_max << endl;
    cout << "Maximum value for double = "       << doubleobj.m_max << endl;
    cout << "Maximum value for nanoseconds = "  << nanosecondseobj.m_max.count( ) << endl;
    cout << "Maximum value for milliseconds = " << millisecondseobj.m_max.count( ) << endl;
    cout << "Maximum value for seconds = "      << secondseobj.m_max.count( ) << endl;
}
ClK
  • 105
  • 7
Guest
  • 1
  • 1