2

I have a class A templated with a Scalar which can be real- or complex-valued. It has a method realPart which is supposed to return the real part of the number. If Scalar is real-valued, it should just return the original Scalar, and .real() if it's of complex type.

When writing

#include <complex> #include <iostream> template<class Scalar> class A { public: A (const Scalar z): z_(z) { } Scalar realPart() { return z_.real(); } private: Scalar z_; }; int main() { A<std::complex<double>> z0((1.0, 2.0)); std::cout << z0.realPart() << std::endl; // check A<double> z1(1.0); std::cout << z1.realPart() << std::endl; // mööp } 

the compiler will complain at z1.realPart() because double doesn't know .real().

How can I guard .real() at compile time?

5
  • what exactly do you want to happen with double ? Commented Jun 9, 2015 at 15:52
  • 1
    You can create template specialization for complex type. Commented Jun 9, 2015 at 15:52
  • @DavidHaim In case of double, just return z_, like you would expect mathematically. Commented Jun 9, 2015 at 15:53
  • so like @AkashPradhan said create a template specialization for it. Commented Jun 9, 2015 at 15:56
  • See stackoverflow template conditionals with type traits stackoverflow.com/questions/6251889/type-condition-in-template Commented Jun 9, 2015 at 15:58

1 Answer 1

7

This can be done with a simple is_complex trait and SFINAE:

template<class T> struct is_complex : std::false_type {}; template<class T> struct is_complex<std::complex<T>> : std::true_type {}; template<class Scalar> class A { public: A(const Scalar z) : z_(z) { } template<class S = Scalar, std::enable_if_t<is_complex<S>{}>* = nullptr> Scalar realPart() { return z_.real(); } template<class S = Scalar, std::enable_if_t<!is_complex<S>{}>* = nullptr> Scalar realPart() { return z_; } private: Scalar z_; }; 
Sign up to request clarification or add additional context in comments.

4 Comments

Why is class S template argument needed? Could not you use is_complex<Scalar>?
@Eugene The substitution failure has to occur within the immediate context of the template. The "outer" template of the entire class is not the immediate context of the member function template. So we use a dummy parameter to alias it.
After adding #include <type_traits> and #include <complex>, I'm getting ‘std::enable_if_t’ has not been declared. This is with GCC 5.1.1. Is there something I forgot to add?
enable_if_t is c++14. it's equivalent to typename std::enable_if<T>::type - see en.cppreference.com/w/cpp/types/enable_if

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.