boost::hana::is_valid fails to compile with gcc8 (and more) and --std=c++14

184 views Asked by At

I use this code with std=c++14 and gcc7.3:

#include <iostream>
#include <string>
#include <type_traits>
#include <boost/hana/assert.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/type.hpp>
namespace hana = boost::hana;

template<class T>
bool foo(T elem)
{
    constexpr auto has_overload_to_string = hana::is_valid([](auto t) -> decltype(to_string(t)) {});
    constexpr bool hasOverloadTo_string = has_overload_to_string(elem);
    return hasOverloadTo_string;
}

int main()
{ 
    std::string elem;
    std::cin >> elem;
    foo(elem);
}  

And it works fine : demo

If now I use gcc10.1, I got this error: demo fail

prog.cc: In instantiation of 'bool foo(T) [with T = std::__cxx11::basic_string<char>]':
prog.cc:41:13:   required from here
prog.cc:27:38: error: temporary of non-literal type 'foo<std::__cxx11::basic_string<char> >::<lambda(auto:1)>' in a constant expression
   27 |      [[maybe_unused]] constexpr auto has_overload_to_string =
      |                                      ^~~~~~~~~~~~~~~~~~~~~~
prog.cc:28:21: note: 'foo<std::__cxx11::basic_string<char> >::<lambda(auto:1)>' is not literal because:
   28 |      hana::is_valid([](auto t) -> decltype(to_string(t)) {});
      |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: note:   'foo<std::__cxx11::basic_string<char> >::<lambda(auto:1)>' is a closure type, which is only literal in C++17 and later 

My question is : Is gcc7.3 too permissive with C++14 and is_valid works when it shouldn't or gcc8 and more add a bug with C++14 ?

1

There are 1 answers

1
Jason Rice On BEST ANSWER

The error has nothing to do with hana::is_valid, but the lambda is not valid in a constant expression in C++14.

There is already a good language lawyer answer for this here: https://stackoverflow.com/a/32697323/800347

Clang also consistently provides an error, so it's clear that previous versions of gcc were incorrect in allowing this.

To workaround this, simply remove the constexpr qualifier to your variable declaration.