template function that accepts const and non-const

Discussion in 'C++' started by u.int.32.t, Apr 22, 2007.

  1. u.int.32.t

    u.int.32.t Guest

    Is there a way to make a single template function that will accept
    both const and non-const parameter types by reference without making a
    copy?

    For example, I can write this which will accept both, but will always
    make a copy:

    template<typename T1>
    void accept(T1 t);

    Thanks for your time.
    u.int.32.t, Apr 22, 2007
    #1
    1. Advertising

  2. u.int.32.t

    Rolf Magnus Guest

    u.int.32.t wrote:

    > Is there a way to make a single template function that will accept
    > both const and non-const parameter types by reference without making a
    > copy?
    >
    > For example, I can write this which will accept both, but will always
    > make a copy:
    >
    > template<typename T1>
    > void accept(T1 t);
    >
    > Thanks for your time.


    Use a reference:

    template<typename T1>
    void accept(T1& t);
    Rolf Magnus, Apr 22, 2007
    #2
    1. Advertising

  3. u.int.32.t

    u.int.32.t Guest

    On Apr 22, 10:23 am, Rolf Magnus <> wrote:
    > u.int.32.t wrote:
    > > Is there a way to make a single template function that will accept
    > > both const and non-const parameter types by reference without making a
    > > copy?

    >
    > > For example, I can write this which will accept both, but will always
    > > make a copy:

    >
    > > template<typename T1>
    > > void accept(T1 t);

    >
    > > Thanks for your time.

    >
    > Use a reference:
    >
    > template<typename T1>
    > void accept(T1& t);


    Yes but this won't work if accept is called as:

    accept(5);

    For example.
    u.int.32.t, Apr 23, 2007
    #3
  4. u.int.32.t

    Ian Collins Guest

    u.int.32.t wrote:
    > Is there a way to make a single template function that will accept
    > both const and non-const parameter types by reference without making a
    > copy?
    >
    > For example, I can write this which will accept both, but will always
    > make a copy:
    >
    > template<typename T1>
    > void accept(T1 t);
    >
    > Thanks for your time.
    >

    Why would you want to? If you want to accept both const and non-const
    parameters by reference, the function can't modify them. So just use

    template <typename T1>
    void accept(const T1& t);

    --
    Ian Collins.
    Ian Collins, Apr 23, 2007
    #4
  5. u.int.32.t wrote:
    ....
    >> Use a reference:
    >>
    >> template<typename T1>
    >> void accept(T1& t);

    >
    > Yes but this won't work if accept is called as:
    >
    > accept(5);
    >
    > For example.
    >


    Then overload accept.

    template <typename T>
    void accept( T & x );

    template <typename T>
    void accept( const T & x );

    int main()
    {
    int i;

    accept( i );
    accept( 5 );
    }


    .... if you really want to live on the thin edge implement the const
    version like this:

    template <typename T>
    void accept( const T & x )
    {
    T t(x);
    accept(t);
    }

    .... don't do this unless you are sure that no-one will misuse it as
    strange things will happen if you expect modifications to the parameter
    to mean anything.
    Gianni Mariani, Apr 23, 2007
    #5
  6. u.int.32.t

    u.int.32.t Guest

    On Apr 22, 4:33 pm, Ian Collins <> wrote:
    > u.int.32.t wrote:
    > > Is there a way to make a single template function that will accept
    > > both const and non-const parameter types by reference without making a
    > > copy?

    >
    > > For example, I can write this which will accept both, but will always
    > > make a copy:

    >
    > > template<typename T1>
    > > void accept(T1 t);

    >
    > > Thanks for your time.

    >
    > Why would you want to? If you want to accept both const and non-const
    > parameters by reference, the function can't modify them. So just use
    >
    > template <typename T1>
    > void accept(const T1& t);


    accept was a forwarding function which I now realize can't be done
    fully without changes to the language. And it really did need to allow
    mutable references.
    u.int.32.t, Apr 23, 2007
    #6
  7. u.int.32.t wrote:
    > On Apr 22, 4:33 pm, Ian Collins <> wrote:
    >> u.int.32.t wrote:
    >>> Is there a way to make a single template function that will accept
    >>> both const and non-const parameter types by reference without making a
    >>> copy?
    >>> For example, I can write this which will accept both, but will always
    >>> make a copy:
    >>> template<typename T1>
    >>> void accept(T1 t);
    >>> Thanks for your time.

    >> Why would you want to? If you want to accept both const and non-const
    >> parameters by reference, the function can't modify them. So just use
    >>
    >> template <typename T1>
    >> void accept(const T1& t);

    >
    > accept was a forwarding function which I now realize can't be done
    > fully without changes to the language. And it really did need to allow
    > mutable references.



    NO NO .... be careful with mutable. In some cases it makes perfect
    sense, in some it does not, it really depends on if the mutable elements
    are part of the value or part of the management. e.g. A cache should be
    mutable (because I should be able to change what things are cached even
    if it's a const object), however the data in the cache should not be
    mutable.

    Anyhow, what was wrong with my overloaded method suggestion ?
    Gianni Mariani, Apr 23, 2007
    #7
  8. "Gianni Mariani" <> wrote in message
    news:462c6ae3$0$25485$...
    > u.int.32.t wrote:
    >> On Apr 22, 4:33 pm, Ian Collins <> wrote:
    >>> Why would you want to? If you want to accept both const and non-const
    >>> parameters by reference, the function can't modify them. So just use
    >>>
    >>> template <typename T1>
    >>> void accept(const T1& t);

    >>
    >> accept was a forwarding function which I now realize can't be done
    >> fully without changes to the language. And it really did need to allow
    >> mutable references.

    >
    >
    > NO NO .... be careful with mutable. In some cases it makes perfect sense,
    > in some it does not, it really depends on if the mutable elements are part
    > of the value or part of the management. e.g. A cache should be mutable
    > (because I should be able to change what things are cached even if it's a
    > const object), however the data in the cache should not be mutable.
    >


    Uhm, I think you're misinterpreting u.int.32.t :). What he's saying has
    nothing to do with the C++ keyword 'mutable', but with the meaning of the
    word mutable itself, e.g., the function needs to be allowed to make changes
    to the entity referenced to. From what I understand of it, he has to write a
    forwarding function that is able to forward it's parameters as-is to another
    (probably yet undefined) function. If you define the accept function taking
    a const T&, it can't forward to functions taking a T&, and if you define
    accept() taking a T&, you can't pass it a const T&. So without a change in
    the language, overloading is the only way possible (C++09 will have "r-value
    references" that, amongst other things, allow you to forward passed-in
    function parameters to other functions as-is)

    - Sylvester
    Sylvester Hesp, Apr 23, 2007
    #8
  9. u.int.32.t

    u.int.32.t Guest

    On Apr 23, 8:45 am, "Sylvester Hesp" <> wrote:
    > "Gianni Mariani" <> wrote in message
    >
    > news:462c6ae3$0$25485$...
    > > u.int.32.t wrote:
    > >> On Apr 22, 4:33 pm, Ian Collins <> wrote:
    > >>> Why would you want to? If you want to accept both const and non-const
    > >>> parameters by reference, the function can't modify them. So just use

    >
    > >>> template <typename T1>
    > >>> void accept(const T1& t);

    >
    > >> accept was a forwarding function which I now realize can't be done
    > >> fully without changes to the language. And it really did need to allow
    > >> mutable references.

    >
    > > NO NO .... be careful with mutable. In some cases it makes perfect sense,

    [snip]

    > Uhm, I think you're misinterpreting u.int.32.t :). What he's saying has
    > nothing to do with the C++ keyword 'mutable', but with the meaning of the
    > word mutable itself, e.g., the function needs to be allowed to make changes
    > to the entity referenced to. From what I understand of it, he has to write a
    > forwarding function that is able to forward it's parameters as-is to another
    > (probably yet undefined) function. If you define the accept function taking
    > a const T&, it can't forward to functions taking a T&, and if you define
    > accept() taking a T&, you can't pass it a const T&. So without a change in
    > the language, overloading is the only way possible (C++09 will have "r-value
    > references" that, amongst other things, allow you to forward passed-in
    > function parameters to other functions as-is)


    Yes, this is exactly it.

    For now, I am probably going to do the equivalent of:

    template<typename T>
    void accept(T & t); // T=const T when necessary

    and in the cases where I call accept like:

    accept(someRvalueFromFunction())

    I'll change it to:

    accept(static_cast<const T&>(someRvalueFromFunction());

    How does that sound?
    u.int.32.t, Apr 23, 2007
    #9
  10. u.int.32.t

    Ian Collins Guest

    u.int.32.t wrote:
    >
    > For now, I am probably going to do the equivalent of:
    >
    > template<typename T>
    > void accept(T & t); // T=const T when necessary
    >
    > and in the cases where I call accept like:
    >
    > accept(someRvalueFromFunction())
    >
    > I'll change it to:
    >
    > accept(static_cast<const T&>(someRvalueFromFunction());
    >
    > How does that sound?
    >

    Why can't you just overload accept for const?

    --
    Ian Collins.
    Ian Collins, Apr 23, 2007
    #10
  11. u.int.32.t

    u.int.32.t Guest

    On Apr 23, 12:42 pm, Ian Collins <> wrote:
    > u.int.32.t wrote:
    >
    > > For now, I am probably going to do the equivalent of:

    >
    > > template<typename T>
    > > void accept(T & t); // T=const T when necessary

    >
    > > and in the cases where I call accept like:

    >
    > > accept(someRvalueFromFunction())

    >
    > > I'll change it to:

    >
    > > accept(static_cast<const T&>(someRvalueFromFunction());

    >
    > > How does that sound?

    >
    > Why can't you just overload accept for const?


    Because accept is in really an polymorphic n-ary forwarding function.
    I think it would be prohibitive to have overloads for each
    permutation.

    If it were just accept(T1), that would work, but its really
    accept(T1,T2,T3,T4,...) etc, etc.
    u.int.32.t, Apr 24, 2007
    #11
  12. u.int.32.t

    Ian Collins Guest

    u.int.32.t wrote:
    > On Apr 23, 12:42 pm, Ian Collins <> wrote:
    >
    >>u.int.32.t wrote:
    >>
    >>
    >>>For now, I am probably going to do the equivalent of:

    >>
    >>>template<typename T>
    >>>void accept(T & t); // T=const T when necessary

    >>
    >>>and in the cases where I call accept like:

    >>
    >>>accept(someRvalueFromFunction())

    >>
    >>>I'll change it to:

    >>
    >>>accept(static_cast<const T&>(someRvalueFromFunction());

    >>
    >>>How does that sound?

    >>
    >>Why can't you just overload accept for const?

    >
    >
    > Because accept is in really an polymorphic n-ary forwarding function.
    > I think it would be prohibitive to have overloads for each
    > permutation.
    >
    > If it were just accept(T1), that would work, but its really
    > accept(T1,T2,T3,T4,...) etc, etc.
    >

    I see. I still think you are taking a risk mixing const and non-const
    parameters. You'll have to find a way of making sure a const object
    does not get passed to a function expecting a non-const.

    --
    Ian Collins.
    Ian Collins, Apr 24, 2007
    #12
    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. Robert Allan Schwartz
    Replies:
    1
    Views:
    397
    Victor Bazarov
    Aug 9, 2004
  2. Fabian Wein
    Replies:
    8
    Views:
    454
    terminator
    Jul 26, 2007
  3. Javier
    Replies:
    2
    Views:
    561
    James Kanze
    Sep 4, 2007
  4. fungus
    Replies:
    13
    Views:
    887
    fungus
    Oct 31, 2008
  5. none
    Replies:
    3
    Views:
    3,260
    James Kanze
    May 20, 2010
Loading...

Share This Page