template deduction of array size

Discussion in 'C++' started by Gianni Mariani, Dec 3, 2003.

  1. Does anyone know if this is supposed to work ?

    template <unsigned N>
    int strn( const char str[N] )
    {
    return N;
    }

    #include <iostream>

    int main()
    {
    std::cout << strn( "abcd" );
    }

    error: no matching function for call to `strn(const char[5])'
     
    Gianni Mariani, Dec 3, 2003
    #1
    1. Advertising

  2. Gianni Mariani

    Dan W. Guest

    On 03 Dec 2003 17:27:52 EST, Gianni Mariani <>
    wrote:

    >
    >Does anyone know if this is supposed to work ?
    >
    >template <unsigned N>
    >int strn( const char str[N] )
    >{
    > return N;
    >}
    >
    >#include <iostream>
    >
    >int main()
    >{
    > std::cout << strn( "abcd" );
    >}
    >
    >error: no matching function for call to `strn(const char[5])'
    >


    Geez, I read an article in CUJ long time ago that dealt with this very
    situation... I think you need to templetize with sizeof().

    Hope I inspire you in the right general direction.
     
    Dan W., Dec 3, 2003
    #2
    1. Advertising

  3. Gianni Mariani

    Dave Guest

    > template <unsigned N>
    > int strn( const char str[N] )
    > {
    > return N;
    > }
    >
    > #include <iostream>
    >
    > int main()
    > {
    > std::cout << strn( "abcd" );
    > }
    >
    > error: no matching function for call to `strn(const char[5])'


    I think not since neither Comeau nor VC++ 7.1 accept it (results below), but
    I must admit I am perplexed as to why. I know that in general a nontype
    parameter for a function template can be deduced, but there is clearly
    something special about this case. I'll be interested to follow this
    thread...

    Note that if you change the parameter to bre reference to array, it works...
    Maybe this can hint at why the case you presented fails...


    Comeau:
    "ComeauTest.c", line 11: error: no instance of function template "strn"
    matches the
    argument list
    The argument types that you used are: (const char [5])
    std::cout << strn("abcd");

    VC++ 7.1:
    d:\visual_c++\dot_net\parameter_test\parameter_test\main.cpp(11) : error
    C2784: 'int strn(const char [N])' : could not deduce template argument for
    'const char [N]' from 'const char [5]'
    d:\visual_c++\dot_net\parameter_test\parameter_test\main.cpp(4) :
    see declaration of 'strn'
     
    Dave, Dec 3, 2003
    #3
  4. Gianni Mariani

    Dave Guest

    "Gianni Mariani" <> wrote in message
    news:bqlo18$...
    >
    > Does anyone know if this is supposed to work ?
    >
    > template <unsigned N>
    > int strn( const char str[N] )
    > {
    > return N;
    > }
    >
    > #include <iostream>
    >
    > int main()
    > {
    > std::cout << strn( "abcd" );
    > }
    >
    > error: no matching function for call to `strn(const char[5])'
    >


    One other thought: Both the parameter and the argument should decay to a
    pointer. (The argument would not if it were reference, but that's not the
    case here...). I wonder if this is somehow interfering with the deduction
    process...
     
    Dave, Dec 3, 2003
    #4
  5. Dave wrote:

    >>Does anyone know if this is supposed to work ?
    >>
    >>template <unsigned N>
    >>int strn( const char str[N] )
    >>{
    >> return N;
    >>}


    ....

    >>
    >>error: no matching function for call to `strn(const char[5])'

    ...
    > One other thought: Both the parameter and the argument should decay to a
    > pointer. (The argument would not if it were reference, but that's not the
    > case here...). I wonder if this is somehow interfering with the deduction
    > process...


    Yes, a reference seems to work, but why does the non reference version
    fail ?

    template <unsigned N>
    int strn( const char ( & str )[N] )
    {
    return N;
    }

    #include <iostream>

    int main()
    {
    std::cout << strn( "abcd" );
    }


    OK - I solved my problem.
     
    Gianni Mariani, Dec 3, 2003
    #5
  6. Gianni Mariani

    Dan W. Guest

    On Wed, 03 Dec 2003 17:42:53 -0500, Dan W. <>
    wrote:

    >On 03 Dec 2003 17:27:52 EST, Gianni Mariani <>
    >wrote:
    >
    >>
    >>Does anyone know if this is supposed to work ?
    >>
    >>template <unsigned N>
    >>int strn( const char str[N] )
    >>{
    >> return N;
    >>}
    >>
    >>#include <iostream>
    >>
    >>int main()
    >>{
    >> std::cout << strn( "abcd" );
    >>}
    >>
    >>error: no matching function for call to `strn(const char[5])'
    >>

    >
    >Geez, I read an article in CUJ long time ago that dealt with this very
    >situation... I think you need to templetize with sizeof().
    >
    >Hope I inspire you in the right general direction.


    What's wrong with sizeof() itself?
     
    Dan W., Dec 3, 2003
    #6
  7. Gianni Mariani wrote in news:bqlo18$:

    >
    > Does anyone know if this is supposed to work ?
    >
    > template <unsigned N>
    > int strn( const char str[N] )
    > {
    > return N;
    > }


    This is effectivly:

    template < unsigned N >
    int strn( char const *str )
    {
    return N;
    }

    >
    > #include <iostream>
    >
    > int main()
    > {
    > std::cout << strn( "abcd" );
    > }
    >
    > error: no matching function for call to `strn(const char[5])'


    Yup the call needs to be:

    std::cout << strn< 5 >( "abcd" );

    Where 5 can be any compile time integral constant you want.

    template < unsigned N >
    unsigned strn( char const (&str)[ N ] )
    {
    return N;
    }

    Or get creative:

    template < typename T, unsigned N >
    unsigned countof( T const (&array)[ N ] )
    {
    return N;
    }

    HTH.

    Rob.
    --
    http://www.victim-prime.dsl.pipex.com/
     
    Rob Williscroft, Dec 3, 2003
    #7
  8. Gianni Mariani

    Dan W. Guest

    On 03 Dec 2003 18:11:37 EST, Gianni Mariani <>
    wrote:

    >Dave wrote:
    >
    >>>Does anyone know if this is supposed to work ?
    >>>
    >>>template <unsigned N>
    >>>int strn( const char str[N] )
    >>>{
    >>> return N;
    >>>}

    >
    >...
    >
    >>>
    >>>error: no matching function for call to `strn(const char[5])'

    >..
    >> One other thought: Both the parameter and the argument should decay to a
    >> pointer. (The argument would not if it were reference, but that's not the
    >> case here...). I wonder if this is somehow interfering with the deduction
    >> process...

    >
    >Yes, a reference seems to work, but why does the non reference version
    >fail ?
    >
    >template <unsigned N>
    >int strn( const char ( & str )[N] )
    >{
    > return N;
    >}
    >
    >#include <iostream>
    >
    >int main()
    >{
    > std::cout << strn( "abcd" );
    >}
    >
    >
    >OK - I solved my problem.


    I think that in the case of the array, the number in the brackets is
    never passed to the function at runtime; --i.e.: it is equivalent to
    passing a pointer, and the number in the brackets is just candy for
    your eyes only; whereas a reference is a unique type.
     
    Dan W., Dec 3, 2003
    #8
  9. Gianni Mariani

    Dan W. Guest

    >
    >I think that in the case of the array, the number in the brackets is
    >never passed to the function at runtime; --i.e.: it is equivalent to
    >passing a pointer, and the number in the brackets is just candy for
    >your eyes only; whereas a reference is a unique type.


    Of course! int[5] is not a compile-time type, but a reference to
    int[5] IS a type.

    Just a C clingon.
     
    Dan W., Dec 3, 2003
    #9
  10. Gianni Mariani

    Dave Guest

    > > template <unsigned N>
    > > int strn( const char str[N] )
    > > {
    > > return N;
    > > }
    > >
    > > #include <iostream>
    > >
    > > int main()
    > > {
    > > std::cout << strn( "abcd" );
    > > }
    > >
    > > error: no matching function for call to `strn(const char[5])'

    >
    > I think not since neither Comeau nor VC++ 7.1 accept it (results below),

    but
    > I must admit I am perplexed as to why. I know that in general a nontype
    > parameter for a function template can be deduced, but there is clearly
    > something special about this case. I'll be interested to follow this
    > thread...
    >
    > Note that if you change the parameter to bre reference to array, it

    works...
    > Maybe this can hint at why the case you presented fails...
    >
    >
    > Comeau:
    > "ComeauTest.c", line 11: error: no instance of function template "strn"
    > matches the
    > argument list
    > The argument types that you used are: (const char [5])
    > std::cout << strn("abcd");
    >
    > VC++ 7.1:
    > d:\visual_c++\dot_net\parameter_test\parameter_test\main.cpp(11) : error
    > C2784: 'int strn(const char [N])' : could not deduce template argument for
    > 'const char [N]' from 'const char [5]'
    > d:\visual_c++\dot_net\parameter_test\parameter_test\main.cpp(4) :
    > see declaration of 'strn'
    >
    >


    Has a conclusion been reached on *why* the original code (shown at the top)
    fails to compile? Even though we have determined that using a reference
    fixes the problem, it is still unclear to me why the original program fails
    to compile...
     
    Dave, Dec 4, 2003
    #10
  11. Gianni Mariani

    Dan W. Guest

    On Wed, 3 Dec 2003 21:06:47 -0700, "Dave" <>
    wrote:

    >> > template <unsigned N>
    >> > int strn( const char str[N] )
    >> > {
    >> > return N;
    >> > }
    >> >
    >> > #include <iostream>
    >> >
    >> > int main()
    >> > {
    >> > std::cout << strn( "abcd" );
    >> > }
    >> >
    >> > error: no matching function for call to `strn(const char[5])'

    >>
    >> I think not since neither Comeau nor VC++ 7.1 accept it (results below),

    >but
    >> I must admit I am perplexed as to why. I know that in general a nontype
    >> parameter for a function template can be deduced, but there is clearly
    >> something special about this case. I'll be interested to follow this
    >> thread...
    >>
    >> Note that if you change the parameter to bre reference to array, it

    >works...
    >> Maybe this can hint at why the case you presented fails...
    >>
    >>
    >> Comeau:
    >> "ComeauTest.c", line 11: error: no instance of function template "strn"
    >> matches the
    >> argument list
    >> The argument types that you used are: (const char [5])
    >> std::cout << strn("abcd");
    >>
    >> VC++ 7.1:
    >> d:\visual_c++\dot_net\parameter_test\parameter_test\main.cpp(11) : error
    >> C2784: 'int strn(const char [N])' : could not deduce template argument for
    >> 'const char [N]' from 'const char [5]'
    >> d:\visual_c++\dot_net\parameter_test\parameter_test\main.cpp(4) :
    >> see declaration of 'strn'
    >>
    >>

    >
    >Has a conclusion been reached on *why* the original code (shown at the top)
    >fails to compile? Even though we have determined that using a reference
    >fixes the problem, it is still unclear to me why the original program fails
    >to compile...
    >


    Because array notation is an ugly thing carried on from C just for
    backward compatibility. The big problem with C arrays is that they do
    not carry size information. At run-time, an array is the same thing as
    a pointer. At compile time as well, for that matter. The only point at
    which the numbers in the brackets are actually used by the compiler is
    when you create the array (allocate space). Thus, you were hoping to
    select the appropriate template instance of a function *given* the
    size of an array, but that array size is NOT given; --i.e.: it doesn't
    get carried along with an array. So scope resolution cannot work.
    To the compiler, int[5] and int[9] are the same type: int*.

    It's as if you open two car garages and say, "odd licence plates go in
    garage A, even license plates in garage B; but the cars coming in
    have NO license plates, so they can't decide where to go.

    References were introduced with C++ and do carry full info with them
    at compile time, thus, scope resolution can work its magic.

    Cheers!
     
    Dan W., Dec 4, 2003
    #11
  12. Gianni Mariani

    tom_usenet Guest

    On 03 Dec 2003 17:27:52 EST, Gianni Mariani <>
    wrote:

    >
    >Does anyone know if this is supposed to work ?
    >
    >template <unsigned N>
    >int strn( const char str[N] )
    >{
    > return N;
    >}
    >
    >#include <iostream>
    >
    >int main()
    >{
    > std::cout << strn( "abcd" );
    >}
    >
    >error: no matching function for call to `strn(const char[5])'


    As others have said, arrays as function parameters decay to pointers.
    But you might find these helpful for writing generic code that works
    for both containers and arrays:

    #include <cstddef>
    #include <iterator>

    template<class Cont>
    std::size_t size(Cont const& c)
    {
    return c.size();
    }

    template<class T, std::size_t N>
    std::size_t size(T const (&array)[N])
    {
    return N;
    }

    template<class T, std::size_t N>
    std::size_t size(T (&array)[N])
    {
    return N;
    }

    template<class Cont>
    typename std::iterator_traits<Cont>::iterator
    begin(Cont& c)
    {
    return c.begin();
    }

    template<class T, std::size_t N>
    T* begin(T (&array)[N])
    {
    return array;
    }

    template<class Cont>
    typename std::iterator_traits<Cont>::const_iterator
    begin(Cont const& c)
    {
    return c.begin();
    }

    template<class T, std::size_t N>
    T const* begin(T const (&array)[N])
    {
    return array;
    }

    template<class Cont>
    typename std::iterator_traits<Cont>::iterator
    end(Cont& c)
    {
    return c.end();
    }

    template<class T, std::size_t N>
    T* end(T (&array)[N])
    {
    return array + N;
    }

    template<class Cont>
    typename std::iterator_traits<Cont>::const_iterator
    end(Cont const& c)
    {
    return c.end();
    }

    template<class T, std::size_t N>
    T const* end(T const (&array)[N])
    {
    return array + N;
    }

    (uncompiled code, may need fixing)

    Tom

    C++ FAQ: http://www.parashift.com/c -faq-lite/
    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
     
    tom_usenet, Dec 4, 2003
    #12
  13. tom_usenet wrote:
    > On 03 Dec 2003 17:27:52 EST, Gianni Mariani <>
    > wrote:
    >

    ....
    >
    > As others have said, arrays as function parameters decay to pointers.
    > But you might find these helpful for writing generic code that works
    > for both containers and arrays:


    I think I'm going to steal this idea ... :)
     
    Gianni Mariani, Dec 4, 2003
    #13
  14. Gianni Mariani

    tom_usenet Guest

    On 04 Dec 2003 11:29:00 EST, Gianni Mariani <>
    wrote:

    >tom_usenet wrote:
    >> On 03 Dec 2003 17:27:52 EST, Gianni Mariani <>
    >> wrote:
    >>

    >...
    >>
    >> As others have said, arrays as function parameters decay to pointers.
    >> But you might find these helpful for writing generic code that works
    >> for both containers and arrays:

    >
    >I think I'm going to steal this idea ... :)


    I think it was Dietmar Kuehl's idea originally. His old boost array
    utility library (that never got past beta) did something similar I
    think.

    Tom

    C++ FAQ: http://www.parashift.com/c -faq-lite/
    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
     
    tom_usenet, Dec 4, 2003
    #14
  15. tom_usenet wrote:
    > On 04 Dec 2003 11:29:00 EST, Gianni Mariani <>
    > wrote:
    >
    >
    >>tom_usenet wrote:
    >>
    >>>On 03 Dec 2003 17:27:52 EST, Gianni Mariani <>
    >>>wrote:
    >>>

    >>
    >>...
    >>
    >>>As others have said, arrays as function parameters decay to pointers.
    >>>But you might find these helpful for writing generic code that works
    >>>for both containers and arrays:

    >>
    >>I think I'm going to steal this idea ... :)

    >
    >
    > I think it was Dietmar Kuehl's idea originally. His old boost array
    > utility library (that never got past beta) did something similar I
    > think.


    I've tried to do somthing similar with the Austria smart pointer
    (releasing under GPL soon) library so that iterators can be managed by
    smart pointers as well. I probably should have factorized it out into
    somthing like this - different problem but same kind of concept.

    What intrigues me is that the more you mess with templates, the code
    grows in unexpected ways. I'm still getting used to them. There are
    significant limitations on templates as defined by the standard, some of
    them because the the legacy of C but I can imagine there is far more to
    template meta-programming than I can see right now.

    The template syntax however is far more obfuscating than I'd like it to
    be. It reminds me of some of the visual programming concepts (auto
    deduction etc). The thing that worries me is that the body of
    programmers that have the fortitude to master templates even at the
    minimal levels is far smaller than those than can master C. The success
    of a language is directly related to the number of competant
    pratitioners and hence my concern. I still run into new compiler
    template bugs and that indicates maturity issues.

    But, on the other hand, I can write 100% generic code which should work
    with far fewer assuptions and hence the satisfaction of creating code
    that I theoretically will never need to update as new features are added
    to the language. (think upgrades from 16bit to 32bit to 64bit).

    .... I rant too much

    G
     
    Gianni Mariani, Dec 4, 2003
    #15
    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. Chris Johnson
    Replies:
    3
    Views:
    479
    C Johnson
    Aug 14, 2003
  2. Replies:
    3
    Views:
    4,350
  3. Peng Yu

    Template argument deduction

    Peng Yu, Apr 16, 2005, in forum: C++
    Replies:
    1
    Views:
    509
    Mike Wahler
    Apr 16, 2005
  4. Fei Liu
    Replies:
    0
    Views:
    425
    Fei Liu
    Oct 25, 2007
  5. Fei Liu
    Replies:
    4
    Views:
    784
    Victor Bazarov
    Oct 26, 2007
Loading...

Share This Page