问题
I need to implement a class, say 'MyClass' using templates.
template<class T>
class MyClass
{
public:
T var1;
T1 var2;
};
There are two member variables var1 and var2. If the class template argument, 'T', is fundamental type (eg: float, double or long double), the types of both the variables var1 and var2 should be the same as the template argument. That is T1 = T in the above example.
But if the template argument is std::complex<T>
, I would like to have
T var1;
std::complex<T> var2;
How to implement it in C++11?
回答1:
A possible solution could be define a simple type traits to extract the correct type
template <typename T>
struct myTypeTraits
{ using type = T; };
template <typename T>
struct myTypeTraits<std::complex<T>>
{ using type = T; };
and MyClass
become
template <typename T>
class MyClass
{
using T0 = typename myTypeTraits<T>::type;
T0 var1;
T var2;
};
If you want to be sure that T
is a fundamental type (or do you mean arithmetic?), is a little more complicated.
A possible way is define a type traits to say (true
or false
) if a type is a std::complex
template <typename>
struct isComplex : public std::false_type
{ };
template <typename T>
struct isComplex<std::complex<T>> : public std::true_type
{ };
Next modify myTypeTraits
with a declaration (no generic definition) and two default bool values
template <typename T, bool = std::is_fundamental<T>::value,
bool = isComplex<T>::value>
struct myTypeTraits;
Next two specializations, the first one for fundamentals and the second one for complexes types
template <typename T>
struct myTypeTraits<T, true, false>
{ using type = T; };
template <typename T>
struct myTypeTraits<std::complex<T>, false, true>
{ using type = T; };
The MyClass
class remain equals but now give an error if you try to instantiate it with (by example) a std::string
.
The following is a full compiling example
#include <complex>
#include <type_traits>
template <typename>
struct isComplex : public std::false_type
{ };
template <typename T>
struct isComplex<std::complex<T>> : public std::true_type
{ };
template <typename T, bool = std::is_fundamental<T>::value,
bool = isComplex<T>::value>
struct myTypeTraits;
template <typename T>
struct myTypeTraits<T, true, false>
{ using type = T; };
template <typename T>
struct myTypeTraits<std::complex<T>, false, true>
{ using type = T; };
template <typename T>
class MyClass
{
public: // public to check with the static_assert()
using T0 = typename myTypeTraits<T>::type;
private:
T0 var1;
T var2;
};
int main ()
{
MyClass<int> mi; // compile
MyClass<std::complex<float>> mc; // compile
// MyClass<std::string> ms; // compilation error
static_assert( std::is_same<int, decltype(mi)::T0>{}, "!" );
static_assert( std::is_same<float, decltype(mc)::T0>{}, "!" );
}
来源:https://stackoverflow.com/questions/47334675/template-type-derivation