oHo
oHo

Reputation: 54621

How to fix "array rvalue" not compiling with gcc-4.8 and clang-3.7?

This snippet requires at least flag -std=c++Ox to compile with GCC-4.9.
Please see online compilation on gcc.godbolt.org.

template <typename T, int SIZE>
int foo (const T (&table) [SIZE])           // T = char
{
  return SIZE ? table[0] : 0;
}

template <typename T, int SIZE>
int bar (const T (&table) [SIZE])           // T = char *
{
    return SIZE ? table[0][0] : 0;
}

int main (int argc, char *argv[])
{
  return argc
       + foo( "foo" )
       + foo( {argv[0][0], argv[1][1]} )    // array rvalue
       + bar( {argv[0],    argv[1]   } );   // array rvalue
}

This compiles fine using GCC-4.9 ... GCC-6.
But fails using previous GCC versions and all Clang versions (last tested is Clang-3.7.1).


Questions

  1. What to change to fix the issue?
    (if possible only adapt the main() body)
  2. Is there a way to make the code compatible with C++03?
    (again, if possible only in the main() body)

GCC-4.8.2 output

example.cpp: In function 'int main(int, char**)':
17 : error: no matching function for call to 'foo(<brace-enclosed initializer list>)'
+ foo( { argv[0][0], argv[1][1] } )
^
17 : note: candidate is:
2 : note: template<class T, int SIZE> int foo(const T (&)[SIZE])
int foo (const T (&table) [SIZE]) // T = char
^
2 : note: template argument deduction/substitution failed:
17 : note: couldn't deduce template parameter 'T'
+ foo( { argv[0][0], argv[1][1] } )
^
18 : error: no matching function for call to 'bar(<brace-enclosed initializer list>)'
+ bar( { argv[0], argv[1] } );
^
18 : note: candidate is:
8 : note: template<class T, int SIZE> int bar(const T (&)[SIZE])
int bar (const T (&table) [SIZE]) // T = char *
^
8 : note: template argument deduction/substitution failed:
18 : note: couldn't deduce template parameter 'T'
+ bar( { argv[0], argv[1] } );
^
Compilation failed

Clang-3.7.1 output

17 : error: no matching function for call to 'foo'
+ foo( { argv[0][0], argv[1][1] } )
^~~
2 : note: candidate template ignored: couldn't infer template argument 'T'
int foo (const T (&table) [SIZE]) // T = char
^
18 : error: no matching function for call to 'bar'
+ bar( { argv[0], argv[1] } );
^~~
8 : note: candidate template ignored: couldn't infer template argument 'T'
int bar (const T (&table) [SIZE]) // T = char *
^
2 errors generated.
Compilation failed

Upvotes: 2

Views: 174

Answers (1)

aschepler
aschepler

Reputation: 72431

You can make this code C++03-compatible by giving names to the temporary arrays C++11 would create.

int main (int argc, char *argv[])
{
    const char il1[] = {argv[0][0], argv[1][1]};
    const char* const il2[] = { argv[0], argv[1] };
    return argc
        + foo( "foo" )
        + foo( il1 )
        + bar( il2 );
}

Upvotes: 2

Related Questions