jeudi 25 avril 2019

Compilation error with std::is_same and operator ||

I don't understand why the following code compiles with Clang++, but not with g++.

#include <memory>

class A {
public:
    virtual ~A() {}
};
class B : public A {
public:
    virtual ~B() {}
};

template <typename Base, typename T>
inline bool isInstanceOf(const T& object) {
    // This line compiles with clang++ (7.0.1) and with gcc (8.3.1)
    // return std::is_same<Base, T>::value ? true : (dynamic_cast<const Base*>(&object) != nullptr);

    // This line compiles only with clang++
    return std::is_same<Base, T>::value || dynamic_cast<const Base*>(&object) != nullptr;
}

int main() {
    isInstanceOf<A>(B());
    isInstanceOf<A>(A());   // Compilation fails

    return 0;
}

The compilation error:

$> g++ -o bin -Wall -Werror test.cpp
test.cpp: In instantiation of 'bool isInstanceOf(const T&) [with Base = A; T = A]':
test.cpp:24:24:   required from here
test.cpp:19:79: error: the compiler can assume that the address of 'object' will never be NULL [-Werror=address]
  std::is_same<Base, T>::value || dynamic_cast<const Base*>(&object) != nullptr;
                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~

cc1plus: all warnings being treated as errors

Why the template instanciation don't skip the second part of the test?

The following code also compiles:

if (std::is_same<Base, T>::value) {
    return true;
} else {
    return dynamic_cast<const Base*>(&object) != nullptr;
}

The compilation of the following code fails too:

if (std::is_same<Base, T>::value) {
    return true;
}

return dynamic_cast<const Base*>(&object) != nullptr;

Aucun commentaire:

Enregistrer un commentaire