Is the compiler allowed to omit a combined call to &* operators for pointer?

gcc disable optimization for a function
pragma gcc optimize
gcc optimization
gcc o
gcc optimization techniques
gcc ofast
gcc optimization levels
gcc flags

I've this template function

template <typename T, typename It, std::enable_if_t<std::is_integral<T>::value, int> = 0>
inline T decode(It &it) {
    static_assert(std::is_same<typename std::iterator_traits<It>::value_type, std::uint8_t>::value, "invalid");
    T* v_p = reinterpret_cast<T*>(&*it);
    it += sizeof(T);
    return *v_p;
}

that is used to decode integers from a raw pointer. The function can be used with any type that has iterator traits, i.e. either pointers to std::uint8_t or iterators to std::uint8_t STL containers with iterators that meet LegacyContiguousIterator requirements.

The function works, but I'm not sure about the performance of the call to &*it when it is a pointer. The operators are needed to get the pointer from an iterator, as explained in this answer, but it seems overkill for POD pointers. Is the compiler allowed to just drop the operations, or it is better to write a specialization for pointers

For a pointer then yes due to the as-if rule allows it.

But in this case, if it isn't a pointer but instead an object with an overloaded dereference operator then the compiler can't do that.

Optimize Options (Using the GNU Compiler Collection (GCC)), The pass tries to combine two instructions and checks if the result can be simplified. If loop This option is enabled by default at optimization levels -O , - O2 , -O3 , -Os . On some targets this flag has no effect because the standard calling Note that -fno-omit-frame-pointer doesn't guarantee the frame pointer is used in all� Compilers that support ConditionalAttribute ignore calls to these methods unless "DEBUG" is defined as a conditional compilation symbol. As you can see, the compiler will omit any calls to Debug members on non-debug builds. However, it will not stop the program from checking your if statement.

If it is a pointer, then &* will be a noop.

But, in any case, whenever you claim something like:

I'm not sure about the performance of [...]

You really need to be able to measure the difference. If you cannot, you are probably worrying about nothing.

Optimize Options, Most optimizations are only enabled if an -O level is set on the command line. For machines that must pop arguments after a function call, the compiler The pass tries to combine two instructions and checks if the result can be simplified. The default can be reverted to -fno-omit-frame-pointer by configuring GCC with the� The compiler heuristically decides which functions are simple enough to be worth integrating in this way. This inlining applies to all functions, even those not declared inline. Enabled at level -O2. -findirect-inlining Inline also indirect calls that are discovered to be known at compile time thanks to previous inlining.

In this case is wrong, because you use an iterator that isn't a pointer but only an object that have a dereference operator, so the basic rule valid for pointers can't be applied in this case.

For more information see the AS-IF-RULE

Errors and Warnings Reference Guide: List of the armcc error and , 59 : function call is not allowed in a constant expression By not declaring a size for the array in the structure, the compiler is not able to allocate a size of the structure. Incomplete types are 84 : invalid combination of type specifiers. The type name 837 : omission of explicit type is nonstandard ("int" assumed). A function� This also requires the availability of copy constructor for Example, even though the compiler is allowed to omit copying the instance. int theInt1 = ctr; // here This uses implicit conversion of Example to unsigned int, provided by the cast operator.

Frequently Asked Questions (FAQ), By January 2008, Ken had started work on a compiler with which to explore ideas ; Is the language called Go or Golang? Go addressed these issues by attempting to combine the ease of programming of an interpreted, We felt it should be possible to have the efficiency, the safety, and the fluidity in a single language. Routine call, lines . This compiles procedure and functions calls to both standard and user-declared routines. Standard routines. Fcp, passed as a parameter , is the pointer to the identifier of the routine being called. Each standard routine has a compiler routine to deal with it.

Optimizing compiler, (April 2009) (Learn how and when to remove this template message). In computing, an optimizing compiler is a compiler that tries to minimize or maximize some This optimization is only possible when the optimizer has access to the called not that number is known at compile time), their bodies can be combined as long� At levels -O1 and higher, -fdefer-pop is the default; this allows the compiler to let arguments accumulate on the stack for several function calls and pop them all at once. -fforward-propagate Perform a forward propagation pass on RTL.

Optimizations in C++ Compilers, On top of this, the compiler is able to move a loop invariant conditional A recursive function that ends in a call to itself can often be rewritten as a loop, Another neat trick the compiler has done is to remove any branching: you There's a pretty neat trick with the and to combine the comparison of \r and \t� Two compilers were written in Meta III, CODOL, a compiler-writing demonstration compiler, and PUREGOL, a dialect of ALGOL 60. (It was pure gall to call it ALGOL). Late in 1964, Lee Schmidt bootstrapped the metacompiler EQGEN, from the PDP-l to the Beckman 420.

Comments
  • it += sizeof(T) is highly suspicious. Iterator increments move to the next element, not the next byte. But sizeof(T) is a size in bytes. The static_assert helps, but an enable_if would be more appropriate.
  • Even more: For a pointer, &* always must compile down to a noop. Simply because once you load the pointee value into the CPU (*), it does not have an address anymore. So, for &* to be meaningful, the dereferenciation step must be omitted, and the address is the nothing else but the current pointer's value.
  • Do std::vector<std::uint8_t> or std::array<std::uint8_t, ...> iterators overload operator&?
  • @GiovanniCerretani No, but all iterator classes overload the dereference operator * (which includes the std::vector iterator).
  • @Someprogrammerdude thanks, of course I meant operator*.
  • @cmaster-reinstatemonica: That's not what * does. * converts a pointer into an lvalue. An lvalue can have its address taken.
  • You forget evil class with overloaded unary operator&.
  • @Jarod42 Hm... for that to happen we would need to specialize std::iterator_traits for a particular pointer so that the standard pointer specialization doesn't kick in, because otherwise given OP claims It is a pointer, and given the static_assert in the question, then It has to be std::uint8_t *. I think.
  • indeed, std::uint8_t * is fine. but without the static_assert, MyClass * might be problematic.
  • We don't know if it is an iterator. In fact it += sizeof(T) indicates that it's not supposed to be.
  • Exactly. With an iterator, there is no guarantee that the bytes are actually consecutive in memory, so the reinterpret_cast<> may easily invoke undefined behavior. I would write such a function using a char*, or just do the reinterpret_cast<> where I need it. That's clearer than hiding the cast away in a templated function.
  • great observation... i do not note these particular
  • @Someprogrammerdude The fact that += is used on the iterator does not mean that the bytes are actually stored consecutively. All the += forces is, that the iterator must be a random access iterator.
  • @cmaster-reinstatemonica thanks for the particular. I'm going to edit the question changing the iterator type to LegacyContiguousIterator requirements.