Reputation: 267
template<typename T>
if (std::is_same<T, FrontCameraSegment>::value) {
height = segment.height;
}
I have a template to process several sensors. One sends me a height property, the others do not. I need that value once in my code, the rest of the Visualize()
function is the same for every sensor.
So I wanted to check whether T is_same
with FrontCameraSegment and then I wanted to use the segment.height property once.
However, the compiler says that "height"
is not a member of all elements passed to T
which is logic.
Casts don't work because of the same reason.
Restructuring the sensors using inheritance is not possible (I am not allowed to do that part).
So my question: How can I tell the compiler that I checked that height
is a member?
Upvotes: 1
Views: 638
Reputation: 217293
In C++17, you could use constexpr if:
template<typename T>
void foo(T& segment)
{
if constexpr (std::is_same<T, FrontCameraSegment>::value) {
height = segment.height;
}
// ...
}
Before, you have to use some specialization/dispatching:
// fallback
template<typename T>
void setHeightIfPossible(float& height, const T& segment) { /* Empty */ }
void setHeightIfPossible(float& height, const FrontCameraSegment& segment) {
height = segment.height;
}
template<typename T>
void foo(T& segment)
{
// ...
setHeightIfPossible(height, segment);
// ...
}
Upvotes: 3
Reputation: 69882
use a enable-if-style functor to optionally apply the height, for example:
#include <utility>
#include <iostream>
namespace notstd {
template<typename... Ts> struct make_void { typedef void type;};
template<typename... Ts> using void_t = typename make_void<Ts...>::type;
}
struct Sensor1
{
int width;
};
struct Sensor2
{
int width;
int height;
};
template<class Sensor, typename = void>
struct height_reader
{
template<class SensorArg>
void operator()(SensorArg&& source, int& target) const
{
// no-op
}
};
template<class Sensor>
struct height_reader<Sensor,
notstd::void_t<decltype(std::declval<Sensor>().height)>>
{
template<class SensorArg>
void operator()(SensorArg&& source, int& target) const
{
target = source.height;
}
};
struct Readings
{
int width = 0, height = 0;
template<class Sensor> void apply_sensor(Sensor&& sensor)
{
width = sensor.width;
height_reader<Sensor> hr;
hr(sensor, height);
}
};
void emit(int i)
{
std::cout << i << std::endl;
}
int main()
{
Sensor1 s1 { 1 };
Sensor2 s2 { 2, 3 };
Readings r;
r.apply_sensor(s1);
r.apply_sensor(s2);
emit(r.height);
}
Upvotes: 0