1
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?

Nipun
  • 2,217
  • 5
  • 23
  • 38
user3932876
  • 247
  • 2
  • 11
  • 1
    Possible duplicate of ["constexpr if" vs "if" with optimizations - why is "constexpr" needed?](https://stackoverflow.com/questions/40972666/constexpr-if-vs-if-with-optimizations-why-is-constexpr-needed) – LogicStuff Aug 31 '17 at 06:29
  • You need to provide specializations for your template based on the result of `std::is_same::value` – user0042 Aug 31 '17 at 06:32
  • @LogicStuff Thanks for pointing to the right answer. But I disagree that this is a duplicate. Duplicate means duplicate question, in this case it is only the same answer to two different questions. Please see also https://meta.stackoverflow.com/a/266246/1023911 and https://meta.stackoverflow.com/q/292329/1023911. – Werner Henze Aug 31 '17 at 07:31
  • @WernerHenze - No, duplicate means the same answer. That's why when closing, the close layout has the title "**This question already has an answer here:**". Naturally, the answer also has to be easily applicable. – StoryTeller - Unslander Monica Aug 31 '17 at 07:44
  • @StoryTeller But both the question and answer you linked is proper only for compilers supporting C++17, thus people limited to older standards will not search for `constexpr if`, but more likely for for more universal answer like OP did (eg. SFINAE). So problem is more general than C++17 – R2RT Aug 31 '17 at 07:56
  • @R2RT - ? I didn't link to any question. I commented on the whole "exact dupte" thing. – StoryTeller - Unslander Monica Aug 31 '17 at 07:57
  • Oh, right, StorryTeller sorry, should have written to @LogicStuff. – R2RT Aug 31 '17 at 08:00
  • @StoryTeller Did you read meta.stackoverflow.com/a/266246/1023911 and meta.stackoverflow.com/q/292329/1023911 as I suggested? These discussions disagree with your view. And please don't only cite partially, the complete text is "This question has been asked before and already has an answer.". Focus on "this question has been asked before"! – Werner Henze Aug 31 '17 at 15:06
  • @WernerHenze - I suggest you take a closer look before wrongfully citing and accusing someone of cherry picking. [Here's a closed question as an example](https://stackoverflow.com/questions/45960484/dynamic-allocation-of-a-3d-array-in-c). The UX is quite clear. We point questions to their answers. The closed dupe remains as a sign-post. The answer needs to be applicable, but the question not *an exact* dupe. Also, 3 year old discussions don't always exhibit the spirit of the site in present day. – StoryTeller - Unslander Monica Aug 31 '17 at 17:02
  • @StoryTeller I searched for newer discussions and found https://meta.stackoverflow.com/questions/341061/a-duplicate-or-near-duplicate-answer-doesnt-automatically-mean-that-a-questio?noredirect=1&lq=1. But this question was closed as being a duplicate of the old question that I linked. So I do not see why the old answers are not correct anymore. Your example of a closed duplicate is like "Look there, I did the same thing another time, so I must be right." That's quite funny. – Werner Henze Aug 31 '17 at 17:53
  • @WernerHenze - My example was to illustrate the UX, which you misquoted. And your obnoxious responses mean this "discussion" is over. – StoryTeller - Unslander Monica Aug 31 '17 at 17:56

2 Answers2

3

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);
    // ...
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
0

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);
}
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142