4

I am attempting to use the new c++17 class template deduction and it all seems to work fine until I apply const. This is a small example of the trouble I'm facing:

#include <type_traits>

template <typename T>
struct X
{
    T _data;

    X(void) = default;
    X(T && data) : _data{ data } {}

    constexpr bool const_x(void) { return false; }
    constexpr bool const_x(void) const { return true; }
};

template <typename T>
X(T &&) -> X<std::remove_reference_t<T>>;

int main(void)
{
    X<int> a;
    const X<int> b{};

    X c{ 10 };
    const X d{ 10 };

    static_assert(!a.const_x());
    static_assert(b.const_x());

    static_assert(!c.const_x());
    static_assert(d.const_x()); // assert fails
}

it appears that when a const X is deducing its types, the const-ness is not carried through. I know this is possible:

template <typename T>
X(T &&) -> const X<std::remove_reference_t<X>>;

but this would make every deduced type const X.

If anyone has any information or help, it would be greatly appreciated!

EDIT I am using GCC-7.1.0

  • https://godbolt.org/g/kRdTpJ clang trunk has no problem with your code. gcc trunk also has no issues: https://godbolt.org/g/TpneVq looks like just a compiler bug. Presumably you were trying with gcc 7.1? https://godbolt.org/g/j6W3dB (fails on that line) – xaxxon Jul 25 '17 at 01:04
  • Do you have any errors when compiling? Or only during execution? – Magrones Jul 25 '17 at 01:04
  • @Fenixrw it's a static assert that's failing -- that's only a compile-time issue – xaxxon Jul 25 '17 at 01:05
  • @xaxxon does this fully compile on clang? – Fletcher Blight Jul 25 '17 at 01:07
  • @FletcherBlight i posted the link...Here's the link with the "link" option turned on.. https://godbolt.org/g/qm77Mx – xaxxon Jul 25 '17 at 01:07
  • @xaxxon thankyou for that, it does appear to be a compiler bug then – Fletcher Blight Jul 25 '17 at 01:09
  • C++17 support is still sketchy (7/2017) on all released compilers. Stick with '14 if you want stability. – xaxxon Jul 25 '17 at 01:10

1 Answers1

9

This is a compiler bug - specifically gcc bug 80990. There are two separate parts here - the deduction, and the const. The declaration:

const X d{ 10 };

will first perform class template argument deduction to pick which X specialization d is (so X<int> due to the deduction guide), and then the const is added on top of that (so X<int> const).


Note also that this:

template <typename T>
X(T &&) -> const X<std::remove_reference_t<X>>;

is ill-formed. You cannot use cv-qualifiers there.

xaxxon
  • 19,189
  • 5
  • 50
  • 80
Barry
  • 286,269
  • 29
  • 621
  • 977