Search code examples
c++c++14autoboost-hana

use of boost::hana::eval_if_t before deduction of auto


A code snippet says more than a couple of paragraphs:

#include <boost/hana/fwd/eval_if.hpp>
#include <boost/hana/core/is_a.hpp>                                                                                                                                       
#include <iostream>
#include <functional>

using namespace boost::hana;

template<class arg_t>
decltype(auto) f2(arg_t const& a)
{
    constexpr bool b = is_a<std::reference_wrapper<std::string>,
                            arg_t>;

    auto wrapper_case = [&a](auto _) -> std::string&
                        { return _(a).get(); };

    auto default_case = [&a]() -> arg_t const&
                        { return a; };

    return eval_if(b, wrapper_case, default_case);
}

int main()
{
    int a = 3;
    std::string str = "hi!";
    auto str_ref = std::ref(str);

    std::cout << f2(a) << ", " << f2(str) << ", " << f2(str_ref)
              << std::endl;
}

The compiler error is:

$> g++ -std=c++14 main.cpp
main.cpp: In instantiation of ‘decltype(auto) f2(const arg_t&) [with arg_t = int]’:
main.cpp:42:22:   required from here
main.cpp:31:19: error: use of ‘constexpr decltype(auto) boost::hana::eval_if_t::operator()(Cond&&, Then&&, Else&&) const [with Cond = const bool&; Then = f2(const arg_t&) [with arg_t = int]::<lambda(auto:1)>&; Else = f2(const arg_t&) [with arg_t = int]::<lambda(auto:2)>&]’ before deduction of ‘auto’
     return eval_if(b, wrapper_case, default_case);
            ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

There's no recursion, I use gcc-6.0.2 which presumably has solved some bugs about decltype(auto) and has a full working C++14 implementation, and also fits the boost::hana requirements, so, my error must be in my implementation but I don't know what is the error about.

NOTE: clang++ 3.8.0 throws a similar compiler error.


Solution

  • First, in case the path doesn't make it clear, boost/hana/fwd/eval_if.hpp is but a forward declaration. If you want to use it in earnest, you need to include the whole thing, i.e., boost/hana/eval_if.hpp. That's the cause of the original error.

    Then, this bool is wrong:

    constexpr bool b = is_a<std::reference_wrapper<std::string>,
                            arg_t>;
    

    Coercing it to bool means that the type no longer carries the value information. Use auto.