440,092 Members | 1,650 Online
Need help? Post your question and get tips & solutions from a community of 440,092 IT Pros & Developers. It's quick & easy.

# template deduction of array size

 P: n/a Does anyone know if this is supposed to work ? template int strn( const char str[N] ) { return N; } #include int main() { std::cout << strn( "abcd" ); } error: no matching function for call to strn(const char[5])' Jul 22 '05 #1
14 Replies

 P: n/a > template int strn( const char str[N] ) { return N; } #include 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_tes t\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_tes t\main.cpp(4) : see declaration of 'strn' Jul 22 '05 #2

 P: n/a On 03 Dec 2003 17:27:52 EST, Gianni Mariani wrote: Does anyone know if this is supposed to work ?template int strn( const char str[N] ){ return N;}#include 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. Jul 22 '05 #3

 P: n/a "Gianni Mariani" wrote in message news:bq********@dispatch.concentric.net... Does anyone know if this is supposed to work ? template int strn( const char str[N] ) { return N; } #include 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... Jul 22 '05 #4

 P: n/a Dave wrote: Does anyone know if this is supposed to work ?template 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 int strn( const char ( & str )[N] ) { return N; } #include int main() { std::cout << strn( "abcd" ); } OK - I solved my problem. Jul 22 '05 #5

 P: n/a Gianni Mariani wrote in news:bq********@dispatch.concentric.net: Does anyone know if this is supposed to work ? template int strn( const char str[N] ) { return N; } This is effectivly: template < unsigned N > int strn( char const *str ) { return N; } #include 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/ Jul 22 '05 #6

 P: n/a 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 int strn( const char str[N] ){ return N;}#include 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 verysituation... I think you need to templetize with sizeof().Hope I inspire you in the right general direction. What's wrong with sizeof() itself? Jul 22 '05 #7

 P: n/a On 03 Dec 2003 18:11:37 EST, Gianni Mariani wrote: Dave wrote:Does anyone know if this is supposed to work ?template 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 versionfail ?template int strn( const char ( & str )[N] ){ return N;}#include 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. Jul 22 '05 #8

 P: n/a >I think that in the case of the array, the number in the brackets isnever passed to the function at runtime; --i.e.: it is equivalent topassing a pointer, and the number in the brackets is just candy foryour 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. Jul 22 '05 #9

 P: n/a > > template int strn( const char str[N] ) { return N; } #include 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_tes t\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_tes t\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... Jul 22 '05 #10

 P: n/a On Wed, 3 Dec 2003 21:06:47 -0700, "Dave" wrote: > template > int strn( const char str[N] ) > { > return N; > } > > #include > > 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, itworks... 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_tes t\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_tes t\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 referencefixes the problem, it is still unclear to me why the original program failsto 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! Jul 22 '05 #11

 P: n/a On 03 Dec 2003 17:27:52 EST, Gianni Mariani wrote: Does anyone know if this is supposed to work ?template int strn( const char str[N] ){ return N;}#include 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 #include template std::size_t size(Cont const& c) { return c.size(); } template std::size_t size(T const (&array)[N]) { return N; } template std::size_t size(T (&array)[N]) { return N; } template typename std::iterator_traits::iterator begin(Cont& c) { return c.begin(); } template T* begin(T (&array)[N]) { return array; } template typename std::iterator_traits::const_iterator begin(Cont const& c) { return c.begin(); } template T const* begin(T const (&array)[N]) { return array; } template typename std::iterator_traits::iterator end(Cont& c) { return c.end(); } template T* end(T (&array)[N]) { return array + N; } template typename std::iterator_traits::const_iterator end(Cont const& c) { return c.end(); } template 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 Jul 22 '05 #12

 P: n/a 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 ... :) Jul 22 '05 #13

 P: n/a 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 Jul 22 '05 #14

 P: n/a 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 worksfor 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 Jul 22 '05 #15

### This discussion thread is closed

Replies have been disabled for this discussion.