Boost logo

Boost :

From: Douglas Gregor (dgregor_at_[hidden])
Date: 2007-10-22 12:04:50


On Oct 21, 2007, at 12:29 AM, Marco Costalba wrote:
> "We decided it's easier to write the definition by listing the errors
> that are not treated as SFINAE failures, and the list we came up with
> is as follows:
>
> 1-errors that occur while processing some entity external to the
> expression, e.g., an instantiation of a template or the generation of
> the definition of an implicitly-declared copy constructor"
>
>
> This limitation seems quite important. As example in the code I posted
> in this thread:
>
> template<int n, typename arg>
> void dispatch_on_value(std::string const& s, arg const& a)
> {
> if ( s == some_string(n) )
>
> /* calls member foo() on the class returned by get_a_class */
> return get_a_class<n>().foo(a);
>
> return dispatch_on_value<n-1>(s, a); // try with next one
> }
>
>
> I could think to use sizeof as a specialization somewhere to filter
> out invalid functions, something like:
>
> sizeof(get_a_class<n>().foo(arg()))
>
> But, if I have read correctly the proposed change, this would result
> in being still considered an error, not under SFINAE case.

If the instantiation of get_a_class<n> fails, this would be an error.
However, if get_a_class<n> has no default constructor, has no
function "foo", has no function "foo" that can take an "arg"
parameter, has several functions "foo" that can take an "arg"
parameter but nothing that is unambiguously the best overload, has a
"foo" that is not a function, or if "arg" has no default
constructor... it's a SFINAE case.

> IMHO closing the doors to instantiation of a class template inside a
> sizeof() expression could cut away a good number of possible cases,
> also not easy to foressen ones (i.e. from where language 'progress'
> normally comes from).

Perhaps it does. However, extending SFINAE to cover instantiation of
class templates is technically infeasible in today's C++ compilers.
Instantiation of class templates causes many side effects in a
typical compiler, altering various data structures along the way.
Sure, it is conceivable that one could use a transaction-based
approach to create a compiler that can roll back any operation,
including instantiation... but it will not happen. The cost of
changing an existing compiler to use this model is immense, and the
payoff is tiny: a few C++ expert hackers will be able to do a little
more. Compiler development is

> In my case, if you have a compile time set of functions/classes and
> you want to choose at run-time one among them using a run-time entity
> (variable, arguments values, etc..) a possible way would be to create
> at compile time a chain of all the instantations of your set, linked
> with recursion, then at run-time return from the recursion chain at
> the point your run-time requirements are met.

You can use SFINAE at each step in the chain to determine whether
that requirement is met.

> Am I missing something?

There are two important points:

        1) The resolution of core issue 339 gives us a *lot* more to work
with in SFINAE cases. We can now easily detect whether various
expressions are valid, which is a huge step forward for template
metaprogramming. It also requires a non-trivial implementation effort
for compiler vendors; I know, because I've implemented most of the
resolution in GCC, which is by far the best prepared for this change.

        2) Concepts are far better for solving this kind of problem than
SFINAE ever will be. Most of the uses of various template tricks---
including SFINAE, tag dispatching, traits, concept checking, and
archetypes---are hacks used to emulate the basic ideas of generic
programming. Concepts express those ideas directly in code,
simplifying their expression and integrating them with the compiler's
type checker.

        - Doug


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk