0

I'm trying to create something similar to std::tuple, a sort of compile-time list using variadic templates and recursive inheritance as shown in the implementation below.

My problem would be that although the implementation shown below works fine on msvc, clang and icc ConstExprList::Get always returns 0 on gcc(trunk version).

If compile the code with -Wall -Werror options enabled, gcc throws the following error:

anonymous is used uninitialized in this function [-Werror=uninitialized].

Note that with optimizations disabled the error does not occur.

Is this a bug in the gcc implementation or am missing something?

#include <type_traits>

template <typename... Args>
class ConstExprList;

template <typename Head, typename... Tail>
class ConstExprList<Head, Tail...> : public ConstExprList<Tail...>
{
public:
    ConstExprList(const Head& head, const Tail&... tail) : ConstExprList<Tail...>(tail...),  m_head(head) {}

    template <std::size_t Idx>
    inline typename std::enable_if<Idx == 0, Head>::type Get(void) const noexcept
    {
        return m_head;
    }

    template <std::size_t Idx>
    inline typename std::enable_if<Idx != 0, Head>::type Get(void) const noexcept
    {
        return ConstExprList<Tail...>::template Get<Idx - 1>();
    }

private:
    const Head& m_head;
};

template <typename Head>
class ConstExprList<Head>
{
public:
    ConstExprList(const Head& head) : m_head(head) {}

    template <std::size_t Idx>
    inline auto Get(void) const noexcept
    {
        static_assert(Idx == 0, "Index out of range");
        return m_head;
    }

private:
    const Head& m_head;
};

int main(void)
{
    ConstExprList<int, int> l(7, 3);

    return l.Get<0>();
}
PraAnj
  • 899
  • 1
  • 10
  • 27
Petok Lorand
  • 955
  • 6
  • 15

1 Answers1

4

The warning is misleading but points out a real problem. m_head is a reference initialised to a temporary. This is not one of the contexts that will cause the temporary's lifetime to be extended, so your references are left dangling.

  • I also found this: https://stackoverflow.com/questions/2784262/does-a-const-reference-class-member-prolong-the-life-of-a-temporary It's interesting, but this makes me even more confused. Why does it work then with calng and msvc? – Petok Lorand Sep 03 '18 at 08:41
  • 1
    @Lorand One of the possible consequences of undefined behaviour is that it behaves exactly the way you expect. –  Sep 03 '18 at 08:45
  • And if these kinf of initialisations don't prolong the lifespan, how/why do expression templates work? – Petok Lorand Sep 03 '18 at 08:47
  • 2
    @Lorand expression templates take care not to store references to temporaries ;) One can e.g. overload for rvalue references and store copies. – n. m. could be an AI Sep 03 '18 at 08:51