SFINAE not applying as expected.

N

Noah Roberts

#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/mpl/int.hpp>
#include <boost/tuple/tuple.hpp>

template < int I >
struct placeholder {};

namespace {
placeholder<0> a1;
placeholder<1> a2;
placeholder<2> a3;
}

template < typename ARGS
, typename IDX >
IDX lookup(ARGS&, IDX idx) { return idx; }

template < typename ARGS
, int IDX >
typename boost::fusion::result_of::at<ARGS, boost::mpl::int_<IDX> >::type lookup(ARGS & args, placeholder<IDX>)
{
return boost::fusion::at_c<IDX>(args);
}

template < typename ARGS
, int IDX >
typename boost::tuples::element<IDX, ARGS>::type lookup(ARGS & args, placeholder<IDX>)
{
return boost::tuples::get<IDX>(args);
}

..... cpp ...

BOOST_AUTO_TEST_CASE(lookup_check)
{
boost::fusion::vector<int, char, std::string> args(42, 'c', "Hello");

//BOOST_CHECK(lookup(args, 13) == 13);
//BOOST_CHECK(lookup(args, a3) == "Hello");

boost::tuple<int, char, std::string> args2(19, 'q', "World");
BOOST_CHECK(lookup(args2, 88) == 88);
BOOST_CHECK(lookup(args2, a2) == 'q');
}


The tuple version of course does not work with the fusion version. The fusion version results in a bunch of errors about incomplete types and such. I would expect this to be filtered out by SFINAE and use only the tuple version, but that is not happening. Why?

Here be the error output:

In file included from /usr/include/boost/fusion/include/at.hpp:10:0,
from /home/nroberts/workspace/static_binder/test/../include/bind.hpp:5,
from /home/nroberts/workspace/static_binder/test/bind_test..cpp:5:
/usr/include/boost/fusion/sequence/intrinsic/at.hpp: In instantiation of ‘boost::fusion::result_of::at<boost::tuples::tuple<int, char, std::basic_string<char> >, mpl_::int_<1> >’:
/home/nroberts/workspace/static_binder/test/bind_test.cpp:18:2: instantiated from here
/usr/include/boost/fusion/sequence/intrinsic/at.hpp:56:16: error: invalid use of incomplete type ‘struct boost::fusion::extension::at_impl<boost::fusion::non_fusion_tag>::apply<boost::tuples::tuple<int, char, std::basic_string<char> >, mpl_::int_<1> >’
/usr/include/boost/fusion/sequence/intrinsic/at.hpp:30:20: error: declaration of ‘struct boost::fusion::extension::at_impl<boost::fusion::non_fusion_tag>::apply<boost::tuples::tuple<int, char, std::basic_string<char> >, mpl_::int_<1> >’

I know why it might not if it had made it past the signature of the function but it has not in this case. I don't understand why it isn't just aborting this function as a non-viable overload.

Thanks.
 
N

Noah Roberts

I believe I have figured out the problem. Please correct me if I'm wrong...

SFINAE only works at the most obvious level. There's a list of valid
deduction failures listed in 14.8.2 and if it's not among those then
SFINAE does not apply. The failure to instantiate some template that's
part of the template instantiation doesn't count. If I tried to access
the type that's failing within the signature I'd get a SFINAE deduction
failure and that function would be skipped. Unfortunately the deduction
of the type I'm trying to create is from within another template call
which is itself failing...and this doesn't apply.

I tested with this code:

typedef void (*A)();
struct B { typedef void type; };

template < typename T >
struct mf { typedef typename T::type type; };

template < typename T >
typename T::type f(T) {}

//template < typename T >
//typename mf<T>::type f(T) {}

template < typename T >
void f(T(*)()) {}

BOOST_AUTO_TEST_CASE(what)
{
f(A());
}

This code compiles and SFINAE applies because there's no type typename
within the A type. But if I comment out the first f() and uncomment the
second one (the one that uses mf), then the deduction of type depends on
the instantiation of mf, which is what fails and this doesn't trigger
SFINAE.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top