function template: deducing non-type argument

Discussion in 'C++' started by Igor R., Apr 6, 2010.

  1. Igor R.

    Igor R. Guest

    Hello,

    I'd like to make 2 different implementations of a function, depending
    on a CT bool parameter, but the caller should not pass a template arg
    explicitly:

    f(true); // one implementation
    f(false); // another one

    Is it possible to deduce a template argument in this case?

    I tried it this way:
    template <bool b>
    void f(bool b)
    {}

    It doesn't work - arg b jusst hides the template arg (MSVC9).

    Thanks!
     
    Igor R., Apr 6, 2010
    #1
    1. Advertising

  2. Igor R.

    Igor R. Guest

    > It's not quite what you're asking for (it involves passing a template
    > parameter rather than an actual parameter), but would this approach suit?
    >
    > #include <iostream>
    >
    > template <bool b> void f();
    >
    > template <>
    > void f<true>()
    > {
    >         std::cout << "true version\n";
    >
    > }
    >
    > template <>
    > void f<false>()
    > {
    >         std::cout << "false version\n";
    >
    > }
    >
    > int main()
    > {
    >         f<true>();
    >         f<false>();



    Well, that's trivial. The problem is that I need the template
    parameter to be deduced.
     
    Igor R., Apr 6, 2010
    #2
    1. Advertising

  3. Igor R.

    Kai-Uwe Bux Guest

    Igor R. wrote:

    >> It's not quite what you're asking for (it involves passing a template
    >> parameter rather than an actual parameter), but would this approach suit?
    >>
    >> #include <iostream>
    >>
    >> template <bool b> void f();
    >>
    >> template <>
    >> void f<true>()
    >> {
    >> std::cout << "true version\n";
    >>
    >> }
    >>
    >> template <>
    >> void f<false>()
    >> {
    >> std::cout << "false version\n";
    >>
    >> }
    >>
    >> int main()
    >> {
    >> f<true>();
    >> f<false>();

    >
    >
    > Well, that's trivial. The problem is that I need the template
    > parameter to be deduced.


    Deduced from what? Could you say what you want a line of client code to look
    like? E.g., one could have:

    f( true ) should print "true version"
    f( false ) should print "false version"
    f( boolean_expression_with_value_unknown_at_compile_time ) ???

    I, too, am not really clear what you are looking for. In particular,

    void f ( bool b ) {
    if ( b ) {
    std::cout << "true version";
    } else {
    std::cout << "false version";
    }
    }

    is also trivial. (If the argument value is known at compile time, an
    optimizing compiler could trim branches during inlining by constant
    propagation.)

    Please explain why the trivial options fall short.


    Best

    Kai-Uwe Bix
     
    Kai-Uwe Bux, Apr 6, 2010
    #3
  4. Igor R.

    Igor R. Guest

    Ok, you're right, my question was stupid. Of course, the actual
    parameter is *allowed* to be a RT value (although in my case it
    isn't), and that's quite enough to disallow such an idea.

    There's a function in my code:

    template<typename T>
    T safeUnwrap(const boost::eek:ptional<T> &t, bool throw_)
    {
    if (throw_ && !t)
    throw EmptyOptional();
    return t ? *t : T();
    }

    Obviously, it's good for default-constructible T only. Now there're
    some non-DC types in the game, and for all of them the function is
    called with throw_ == true. One of the thoughts (the stupid one) was
    to use this correlation to provide another implementation of
    safeUnwrap, which in turn raised the above theoretical question.

    Certainly, it should be sorted out using enable_if/disable_if and the
    type-trait has_nothrow_default_constructor

    Thanks.
     
    Igor R., Apr 6, 2010
    #4
  5. * Igor R.:
    > Ok, you're right, my question was stupid. Of course, the actual
    > parameter is *allowed* to be a RT value (although in my case it
    > isn't), and that's quite enough to disallow such an idea.
    >
    > There's a function in my code:
    >
    > template<typename T>
    > T safeUnwrap(const boost::eek:ptional<T> &t, bool throw_)
    > {
    > if (throw_ && !t)
    > throw EmptyOptional();
    > return t ? *t : T();
    > }
    >
    > Obviously, it's good for default-constructible T only. Now there're
    > some non-DC types in the game,


    From later comment "DC" seems to mean "default constructible".


    > and for all of them the function is
    > called with throw_ == true.


    The function above can't be called for a non-default constructible type T; it
    won't compile.

    Ergo, the code you're showing is not the code that your comment applies to.

    This makes it difficult to help, since we're not telepathic.


    > One of the thoughts (the stupid one) was
    > to use this correlation to provide another implementation of
    > safeUnwrap, which in turn raised the above theoretical question.
    >
    > Certainly, it should be sorted out using enable_if/disable_if and the
    > type-trait has_nothrow_default_constructor


    What's the point of using boost::eek:ptional and translating an empty one to a T()?


    Cheers & hth.,

    - Alf
     
    Alf P. Steinbach, Apr 6, 2010
    #5
  6. Igor R.

    Igor R. Guest

    > The function above can't be called for a non-default constructible type T; it
    > won't compile.


    Sure it won't, as stated: "obviously, it's good for default-
    constructible T only".

    > What's the point of using boost::eek:ptional and translating an empty one to a T()?


    In one layer of code things are stored as optional's; another layer
    should make decisions about how to treat empties.
     
    Igor R., Apr 6, 2010
    #6
  7. "Igor R." <> writes:

    > Hello,
    >
    > I'd like to make 2 different implementations of a function, depending
    > on a CT bool parameter, but the caller should not pass a template arg
    > explicitly:
    >
    > f(true); // one implementation
    > f(false); // another one
    >
    > Is it possible to deduce a template argument in this case?
    >
    > I tried it this way:
    > template <bool b>
    > void f(bool b)
    > {}
    >
    > It doesn't work - arg b jusst hides the template arg (MSVC9).
    >
    > Thanks!


    A quick analysis suggests that your idea runs into the problem that a
    non-type template argument must be a compile-time constant expression,
    whilst the call to your proposed method provides a run-time argument.
    It may be that some clever template metaprogramming might get you from
    the latter to the former but, that not being my bag, I can't immediately
    imagine how it might be achieved. Running through the several motifs
    that do spring to mind always results in the fact that, somewhere along
    the line, it will be required to specify a template argument explicitly
    which, of course, merely shifts the problem without gain.

    Regards

    Paul Bibbings
     
    Paul Bibbings, Apr 6, 2010
    #7
  8. * Igor R.:
    >> The function above can't be called for a non-default constructible
    >> type T; it won't compile.

    >
    > Sure it won't, as stated: "obviously, it's good for default-
    > constructible T only".


    And in that article you wrote "Now there're some non-DC types in the game, and
    for all of them the function is called with throw_ == true."

    The function you showed can't be called with such type.

    This is a self-contradiction.

    But instead of describing existing code, which would be self-contradictory, is
    that perhaps what you'd want to be possible?

    I can imagine that you want e.g. ...

    T const o = safeUnwrap( anOptional );

    .... to throw instead of not compiling when T is not default-constructible and
    anOptional is empty.

    That's possible *if* you can reliably determine at compile time whether T is
    default constructible or not. But it's generally not a good idea to replace
    static type checking with dynamic type checking. So, best advice is, if that's
    what you want to do (this is a bit unclear), don't.


    >> What's the point of using boost::eek:ptional and translating an empty one

    > to a T()?
    >
    > In one layer of code things are stored as optional's; another layer
    > should make decisions about how to treat empties.


    Uhm.


    Cheers & hth.,

    - Alf
     
    Alf P. Steinbach, Apr 6, 2010
    #8
  9. Igor R.

    Kai-Uwe Bux Guest

    Alf P. Steinbach wrote:

    > * Igor R.:
    >>> The function above can't be called for a non-default constructible
    >>> type T; it won't compile.

    >>
    >> Sure it won't, as stated: "obviously, it's good for default-
    >> constructible T only".

    >
    > And in that article you wrote "Now there're some non-DC types in the game,
    > and for all of them the function is called with throw_ == true."
    >
    > The function you showed can't be called with such type.
    >
    > This is a self-contradiction.

    [...]

    Not so fast: he did not claim that the code he posted compiles. Instead, I
    think, what he is after is what should be written instead, so that it
    compiles.


    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Apr 6, 2010
    #9
  10. Igor R.

    James Kanze Guest

    On Apr 6, 3:09 pm, Victor Bazarov <> wrote:
    > Igor R. wrote:


    [...]
    > *Deduction* is only for *types*, not values,


    That's not true. I regularly use something like:

    template<typename T, size_t n>
    T*
    end( T (&array)[n] )
    {
    return array + n;
    }

    and it works. The compiler deduces n.

    > and it's based on the *types* of the arguments which the
    > compiler knows when it sees a call to the template
    > instantiation (still compile-time based).


    From what I gather else thread, what he really needs is two
    functions, one which might return T(), and another that throws,
    no matter what. The obvious solution is two different
    functions.

    --
    James Kanze
     
    James Kanze, Apr 6, 2010
    #10
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. mathieu
    Replies:
    1
    Views:
    296
    Victor Bazarov
    Dec 12, 2006
  2. George2

    Deducing Function Template Arguments

    George2, Mar 12, 2008, in forum: C Programming
    Replies:
    0
    Views:
    292
    George2
    Mar 12, 2008
  3. nguillot
    Replies:
    5
    Views:
    560
  4. James
    Replies:
    10
    Views:
    977
    Alf P. Steinbach
    Nov 28, 2009
  5. , India
    Replies:
    8
    Views:
    463
    James Kanze
    Jul 19, 2010
Loading...

Share This Page