TL;DR Let's say I have a function with a template argument T
that takes a std::vector<T>&
as input (see below), I want to conjugate this vector, if T
is a complex type. How can I do that ?
What I have tried Following https://stackoverflow.com/a/30737105/5913047, I know I can check if a type is complex with
template<class T> struct is_complex : std::false_type {};
template<class T> struct is_complex<std::complex<T>> : std::true_type {};
So I tried:
template<typename T>
void MyFunction(std::vector<T>& MyVector){
// do something
if (is_complex<T>()){
std::transform(MyVector.begin(), MyVector.end(), MyVector.begin(),[](T&c){return std::conj(c););
}
}
but then, if I use this function with a non complex type, the compiler says that conj
is not defined for non complex type. Is there some design to do what I want ?
You are using an if
statement. This requires the code in the if
branch to be compilable, even if you don't need it to be executed.
In c++17, to conditionally compile a piece of code, you can use if constexpr
like this:
if constexpr (is_complex<T>()) {
//^^^^^^^^^
std::transform(MyVector.begin(), MyVector.end(), MyVector.begin(),[](T&c){ return std::conj(c); });
}
Here's a demo.
In c++11, you can use std::enable_if
to write overloads for the case where the type is non-complex, like this:
template<typename T, typename std::enable_if<!is_complex<T>::value, int>::type = 0>
void MyFunction(std::vector<T>& MyVector){
// do something
}
template<typename T, typename std::enable_if<is_complex<T>::value, int>::type = 0>
void MyFunction(std::vector<T>& MyVector){
// do something
std::transform(MyVector.begin(), MyVector.end(), MyVector.begin(),[](T&c){ return std::conj(c); });
}
Here'a a demo.