Code considered only at compile time may contain Undefined Behavior?

6

When designing a function that adds two values of any distinct classes, I can write the following generically:

template <typename T, typename U>
decltype((*(T*)0) + (*(U*)0)) add(T t, U u) {
    return t + u;
}

The interesting part is the return type: decltype((*(T*)0) + (*(U*)0)) . In other words: "The type resulting from the sum of an object of type T with one of type U ".

But to get an object of type T , use (*(T*)0) which, although it is invalid if executed, always results in type T . Another way to get the same result would be: T() + U() . The problem is that it is assumed that there is a default constructor for the types, even though I do not even need a constructor for the function.

My question is: is writing this function really allowed and does not create Undefined Behavior?

More generally, can I use expressions that result in Undefined Behavior when executed, but which has a well-defined type, within a decltype ?

Note: In C ++ 11 it is possible to write:

template <typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
    return t + u;
}

And in C ++ 14 you can write:

template <typename T, typename U>
auto add(T t, U u) {
    return t + u;
}

But that's not relevant to the question.

    
asked by anonymous 21.01.2015 / 16:42

1 answer

1

You can use any valid expression within the decltype. And it does not matter if in case the statement were executed its behavior would be undefined. This is because decltype does not execute the expression and then uses the resulting type. Instead it infers the resulting type from the expression.

In the case of your example, it does not override the null pointer to find the type. He knows that the re-referencing of a T-pointer is a T-value.

Because, it does not have the expression to execute, since, as you said it, this is all done at compile time.

    
29.01.2015 / 07:56