We are migrating to Sun Studio 12.1 and with the new compiler [ CC: Sun C++ 5.10 SunOS_sparc 2009/06/03 ]. I am getting compilation error while compiling a code that compiled fine with earlier version of Sun Compiler [ CC: Sun WorkShop 6 update 2 C++ 5.3 2001/05/15 ].
This is the compilation error I get.
"Sample.cc": Error: Could not find a match for LoopThrough(int[2])
needed in main(). 1 Error(s) detected.
*** Error code 1.
CODE:
#include <iostream>
#define PRINT_TRACE(STR) \
std::cout << __FILE__ << ":" << __LINE__ << ":" << STR << "\n";
template<size_t SZ>
void LoopThrough(const int(&Item)[SZ])
{
PRINT_TRACE("Specialized version");
for (size_t index = 0; index < SZ; ++index)
{
std::cout << Item[index] << "\n";
}
}
/*
template<typename Type, size_t SZ>
void LoopThrough(const Type(&Item)[SZ])
{
PRINT_TRACE("Generic version");
}
*/
int main()
{
{
int arr[] = { 1, 2 };
LoopThrough(arr);
}
}
If I uncomment the code with Generic version, the code compiles fine and the generic version is called. I don't see this problem with MSVC 2010 with extensions disabled and the same case with ideone here.
The specialized version of the function is called. Now the question is, is this a bug in Sun Compiler ?
If yes, how could we file a bug report ?
The compiler is not following the standard in this case and is buggy. Let's review the relevant sections.
First from 13.3/3 we have:
...
— First, a subset of the candidate functions—those that have the
proper number of arguments and meet certain other conditions—is
selected to form a set of viable functions (13.3.2).
— Then the best viable function is selected based on the implicit
conversion sequences (13.3.3.1) needed to match each argument to the
corresponding parameter of each viable function.
So both functions have the same number of arguments and are considered candidates. Now we have to find the best viable function, in
13.3.3:
let ICSi(F) denote the implicit conversion sequence that converts the
ith argument in the list to the type of the ith parameter of viable
function F. 13.3.3.1 defines the implicit conversion sequences and
13.3.3.2 defines what it means for one implicit conversion sequence to be a better conversion sequence or worse conversion sequence than
another
Then we have
Given these definitions, a viable function F1 is defined to be a
better function than another viable function F2 if for all arguments
i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then
— for some argument j, ICSj(F1) is a better conversion sequence than
ICSj(F2), or, if not that,
— F1 is a nontemplate function and F2 is a
template function specialization, or, if not that,
— F1 and F2 are
template functions, and the function template for F1 is more
specialized than the template for F2 according to the partial ordering
rules described in 14.5.5.2, or, if not that,
The two functions are equal for the first rule (adding const), and the second rule doesn't apply (both are templates). So we move to the third rule. From 14.5.5.2 (which I will quote if requested) we learn that the const int version of the function is more specialized than the const Item version, and so the best match is the const int overload, which should then be called.
Your best temporary fix is probably a second overload:
template<size_t SZ>
void LoopThrough(int (&Item)[SZ])
{
LoopThrough(static_cast<const int (&)[SZ]>(Item));
}
Your compiler is buggy. Both overloads have their template arguments deduced, and overload resolution should select the most specialized one. So apart from getting a new compiler, what can you do?
First, it's helpful to realize that -even with conforming compilers- it is generally not a good a idea to have different function template overloads. See e.g. Item 66 of C++ Coding Standards: 101 Rules, Guidelines, and Best Practices by Herb Sutter and Andrei Alexandrescu.
Fortunately, that Item also suggests a possible fix. All you have to do is define a single function template and let that function template delegate the work to a class template function object. You can then partially specialize this class template for ints.
#include <iostream>
#define PRINT_TRACE(STR) \
std::cout << __FILE__ << ":" << __LINE__ << ":" << STR << "\n";
namespace detail {
// primary template
template<typename Type, size_t SZ>
class LoopThroughHelper
{
public:
void operator()(const Type(&Item)[SZ])
{
PRINT_TRACE("Generic version");
}
};
// partial specialization for int arrays
template<size_t SZ>
class LoopThroughHelper<int, SZ>
{
public:
void operator()(const int(&Item)[SZ])
{
PRINT_TRACE("Specialized version");
for (size_t index = 0; index < SZ; ++index)
{
std::cout << Item[index] << "\n";
}
}
};
} // namespace detail
// one function template to rule them all
template<typename Type, size_t SZ>
void LoopThrough(const Type(&Item)[SZ])
{
detail::LoopThroughHelper<Type, SZ>()(Item);
}
int main()
{
{
int arr[] = { 1, 2 };
LoopThrough(arr);
}
}
Most likely, the compiler will inline the call to the function object and completely optimize away the temporary. Hopefully your compiler will also have correctly implemented partial specialization of class templates.
Output on Ideone
Related
I am trying to use operator sizeof... to skip the function for the end of recursion by not calling it if there are no argument
#include<iostream>
template<typename T, typename ...Types>
void Display(T firstArg, Types...Args)
{
std::cout << firstArg << "\n";
std::cout << sizeof...(Types) << "\n";
std::cout << sizeof...(Args) << "\n";
if (sizeof...(Args) > 0)
Display(Args...);
}
int main()
{
Display(1, 2, 3,"hello");
return 0;
}
But I am getting following error for Display(Args...);
error C2780: 'void Display(T,Types...)': expects 2 arguments - 0
provided
Workaround is to add function for the end of recursion (which I want to avoid)
void Display()
{
}
Question is how to avoid end of recursion function
You can’t do this without some workaround, pre-C++17, unless you rewrite the function to not be recursive. The reason is that the entire function body is substituted, including branches of if statements that can never happen. That means that the compiler sees the call to Display() with no arguments, even though it would never have happened at runtime.
Since C++17, the solution to this is to use if constexpr instead of just if. That tells the compiler to evaluate the condition at compile time, and not try to compile the branch which doesn’t execute.
Note that “not try to compile” above is a simplification; the link has more details about what exactly is and isn’t done.
Here is my code:
#include <iostream>
#include "Generator.h" // user-defined class
char getChar(Generator & generator)
{
return generator.generateChar();
}
char getChar(int pos, const string & s)
{
return s[pos];
}
template<typename... StringType>
void func(Generator & generator, StringType &&... str)
{
char ch;
int size = sizeof...(StringType);
// lots of things to do
if (size == 0)
{
ch = getChar(generator);
}
else
{
ch = getChar(1, std::forward<StringType>(str)...); // ERROR here
}
}
int main(int argc, char ** argv)
{
Generator generator;
func(generator);
func(generator, "abc");
return 0;
}
At the beginning I just overloaded the function func and I found there were many similar codes. So I'm considering using the variadic template to get a better design. (How to make a better design if two overload functions are similar)
However I don't know why there is an error:
main.cpp:27:8: error: no matching function for call to 'getChar'
ch = getChar(1, std::forward(str)...);
main.cpp:37:2: note: in instantiation of function template specialization 'func<>' requested here
func(generator);
main.cpp:6:6: note: candidate function not viable: no known conversion from 'int' to 'Generator &' for 1st argument char
getChar(Generator & generator)
main.cpp:11:6: note: candidate function not viable: requires 2 arguments, but 1 was provided char getChar(int pos, const string & s)
By the way, can I have some design to avoid using if...else... working with sizeof...(StringType)?
When a template gets expanded, the entire template code gets expanded, and compiled, in its entirety.
Let's see what happens here:
func(generator);
In the resulting template-generated function, size will be 0, and the resulting function becomes:
if (0 == 0)
{
ch = getChar(generator);
}
else
{
ch = getChar(1);
}
Your compilation error becomes very obvious: getchar(1); does not match any overloaded instance of getChar(). The fact that the if statement is going to always evaluate to true, and the else part will never be executed doesn't matter. The else part must still be valid C++ code, that gets compiled, and it gets optimized away (maybe) only after it is compiled. And it can't be compiled, hence the compilation error.
Now that answers your question "I don't know why there is an error". Now you know. How to fix this becomes a different question, with the answer being, depending on the exact situation, some combination of template specialization, and/or SFINAE.
It looks like the example in your question is an abbreviated example (since the template function will never work, obviously, if the parameter pack has two or more parameters). That's fine (and is 100% compliant with the spirit of showing a minimum, complete, verifiable example), but coming up with an alternative compilable version of the shown code would probably not answer your real question.
I wondered if I could auto deduce the size of an array, which is passed as a template parameter, without (explicitly) passing its size.
The following code both compiles warning-less on g++ 4.8 and clang++ 3.3 (using -std=c++11 -Wall).
#include <iostream>
template<const int* arr>
struct array_container
{
static constexpr int val = arr[1];
array_container() {
std::cout << val << std::endl;
}
// static constexpr int arr_size = ??;
};
constexpr int one[] = { 1 };
constexpr int two[] = { 1, 2 };
int main()
{
// array_container<one> array_one;
array_container<two> array_two;
// (void) array_one;
(void) array_two;
return 0;
}
However, if I remove the two comment signs in main(), I get an out of bound error with both compilers.
Now, this is cool. Somehow the compiler knows the size of the array, though the type of const int* arr is a pointer. Is there any way to get the size of arr, e.g. to complete my comment in array_container?
Of course, you are not allowed to
Use any macros
Store the size in arr (e.g. passing an std::array as template parameter: constexpr std::array<int, 1> one = { 1 }, or using an end marker like '\0' in strings)
Use an additional template parameter for the size that can not be auto deduced (array_container<1, one> array_one).
Maybe std::extent template from <type_traits> header of C++11 standard library is what you want:
#include <iostream>
#include <type_traits>
constexpr int one[] = { 1 };
constexpr int two[] = { 1, 2 };
int main()
{
std::cout << std::extent<decltype(one)>::value << std::endl;
std::cout << std::extent<decltype(two)>::value << std::endl;
return 0;
}
Output:
1
2
template<size_t size>
constexpr size_t arraySize ( const int ( &arrayRef ) [size] ) {
return size;
}
int main(){
int A[1];
int B[2];
cout << arraySize(A) << arraySize(B);
return 0;
}
I believe something like this is what you're looking for, using array references. The syntax for declaring an array reference looks kind of like the syntax for a function pointer. This function template accepts an array reference named arrayRef, which prevents array-to-pointer decay so that compile-time info about array size is preserved. As you can see, the template argument is implicit to the compiler. Note that this can only work when the size can be deduced at compile time. Interestingly, this should still work without naming arrayRef at all. To make the above template more useful, you can add a template parameter to deduce the type of the array as well. I left it out for clarity.
Probably not, as SFINAE only happens in the immediate context, while that error comes from the requirement that UB in constexpr lead to a compile time error, which I think is not immediate. You could try a recursive SFINAE that stops on the UB, but even if it worked you would have to both check the standard and hope it does not change (as it is rather obscure and new).
The easy way is to ise s function to deduce the array size, have to explicitly pass it to the type, then store it in an auto. Probably not what you want.
There are proposals to allow type parameters to be deduced from value parameters, so you could wait for those instead.
Not a solid answer, more of an extended comment, so marked community wiki.
It is indeed possible. I found a solution using SFINAE. What it basically does is produce a substitution error if the index is out of bound (line 3 in this example):
template<class C>
static yes& sfinae(typename val_to_type<
decltype(*C::cont::data), *(C::cont::data + C::pos)>::type );
template<class C>
static no& sfinae(C );
The full source code is on github.
There are only two disadvantages:
You have to specify the type of the array (this can not be avoided)
It only works with g++ 4.8.1 and clang 3.3. g++ fails for empty strings (with a compiler bug). If someone can test for other compilers, that would be appreciated.
I came across this piece of code in "C++ Templates - The complete Guide". I tried my best to find out if this has been explained somewhere. Apologies if it has already been explained
template<int I> void f(int (&)[24/(4-I)]);
template<int I> void f(int (&)[24/(4+I)]);
int main()
{
&f<4>; // ERROR: division by zero (SFINAE doesn't apply)
}
Book does say that this won't compile for a specific reason but I do not understand the template syntax and how the function is called with & operator at the beginning.
Appreciate the help.
Harish
In fact, it does compile. You can also call one of these functions, e.g. the following prints +:
template<int I> void f(int (&)[24/(4-I)]) { std::cout << "-" << std::endl; }
template<int I> void f(int (&)[24/(4+I)]) { std::cout << "+" << std::endl; }
int main()
{
int a[3];
f <4>(a);
}
Anyhow, both template functions f expect a reference to an int array, whose length depends on template parameter I. For instance, I picked a[3] because 24/(4+I) = 24/8 = 3 for I=4.
The function is not called by &f<4>, but only instantiated by taking its address (which actually issues a warning for the unused result).
I guess the book assumes the code won't compile due to the division by zero caused by attempting to instantiate the first overload for I=4, which is not the case.
This is just something that has bothered me for the last couple of days, I don't think it's possible to solve but I've seen template magic before.
Here goes:
To get the number of elements in a standard C++ array I could use either a macro (1), or a typesafe inline function (2):
(1)
#define sizeof_array(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0]))
(2)
template <typename T>
size_t sizeof_array(const T& ARRAY){
return (sizeof(ARRAY)/sizeof(ARRAY[0]));
}
As you can see, the first one has the problem of being a macro (for the moment I consider that a problem) and the other one has the problem of not being able to get the size of an array at compile time; ie I can't write:
enum ENUM{N=sizeof_array(ARRAY)};
or
BOOST_STATIC_ASSERT(sizeof_array(ARRAY)==10);// Assuming the size 10..
Does anyone know if this can be solved?
Update:
This question was created before constexpr was introduced. Nowadays you can simply use:
template <typename T>
constexpr auto sizeof_array(const T& iarray) {
return (sizeof(iarray) / sizeof(iarray[0]));
}
Try the following from here:
template <typename T, size_t N>
char ( &_ArraySizeHelper( T (&array)[N] ))[N];
#define mycountof( array ) (sizeof( _ArraySizeHelper( array ) ))
int testarray[10];
enum { testsize = mycountof(testarray) };
void test() {
printf("The array count is: %d\n", testsize);
}
It should print out: "The array count is: 10"
In C++1x constexpr will get you that:
template <typename T, size_t N>
constexpr size_t countof(T(&)[N])
{
return N;
}
The best I can think of is this:
template <class T, std::size_t N>
char (&sizeof_array(T (&a)[N]))[N];
// As litb noted in comments, you need this overload to handle array rvalues
// correctly (e.g. when array is a member of a struct returned from function),
// since they won't bind to non-const reference in the overload above.
template <class T, std::size_t N>
char (&sizeof_array(const T (&a)[N]))[N];
which has to be used with another sizeof:
int main()
{
int a[10];
int n = sizeof(sizeof_array(a));
std::cout << n << std::endl;
}
[EDIT]
Come to think of it, I believe this is provably impossible to do in a single "function-like call" in C++03, apart from macros, and here's why.
On one hand, you will clearly need template parameter deduction to obtain size of array (either directly, or via sizeof as you do). However, template parameter deduction is only applicable to functions, and not to classes; i.e. you can have a template parameter R of type reference-to-array-of-N, where N is another template parameter, but you'll have to provide both R and N at the point of the call; if you want to deduce N from R, only a function call can do that.
On the other hand, the only way any expression involving a function call can be constant is when it's inside sizeof. Anything else (e.g. accessing a static or enum member on return value of function) still requires the function call to occur, which obviously means this won't be a constant expression.
It's not exactly what you're looking for, but it's close - a snippet from winnt.h which includes some explanation of what the #$%^ it's doing:
//
// RtlpNumberOf is a function that takes a reference to an array of N Ts.
//
// typedef T array_of_T[N];
// typedef array_of_T &reference_to_array_of_T;
//
// RtlpNumberOf returns a pointer to an array of N chars.
// We could return a reference instead of a pointer but older compilers do not accept that.
//
// typedef char array_of_char[N];
// typedef array_of_char *pointer_to_array_of_char;
//
// sizeof(array_of_char) == N
// sizeof(*pointer_to_array_of_char) == N
//
// pointer_to_array_of_char RtlpNumberOf(reference_to_array_of_T);
//
// We never even call RtlpNumberOf, we just take the size of dereferencing its return type.
// We do not even implement RtlpNumberOf, we just decare it.
//
// Attempts to pass pointers instead of arrays to this macro result in compile time errors.
// That is the point.
//
extern "C++" // templates cannot be declared to have 'C' linkage
template <typename T, size_t N>
char (*RtlpNumberOf( UNALIGNED T (&)[N] ))[N];
#define RTL_NUMBER_OF_V2(A) (sizeof(*RtlpNumberOf(A)))
The RTL_NUMBER_OF_V2() macro ends up being used in the more readable ARRAYSIZE() macro.
Matthew Wilson's "Imperfect C++" book also has a discussion of the techniques that are used here.
The Problem
I like Adisak's answer:
template <typename T, size_t N>
char ( &_ArraySizeHelper( T (&arr)[N] ))[N];
#define COUNTOF( arr ) (sizeof( _ArraySizeHelper( arr ) ))
It's what Microsoft uses for the _countof macro in VS2008, and it's got some nice features:
It operates at compile time
It's typesafe (i.e. it will generate a compile-time error if you give it a pointer, which arrays degrade too all too easily)
But as pointed out by Georg, this approach uses templates, so it's not guaranteed to work with local types for C++03:
void i_am_a_banana() {
struct { int i; } arr[10];
std::cout << COUNTOF(arr) << std::endl; // forbidden in C++03
}
Fortunately, we're not out luck.
The Solution
Ivan Johnson came up with a clever approach that wins on all accounts: it's typesafe, compile-time, and works with local types:
#define COUNTOF(arr) ( \
0 * sizeof(reinterpret_cast<const ::Bad_arg_to_COUNTOF*>(arr)) + \
0 * sizeof(::Bad_arg_to_COUNTOF::check_type((arr), &(arr))) + \
sizeof(arr) / sizeof((arr)[0]) )
struct Bad_arg_to_COUNTOF {
class Is_pointer; // incomplete
class Is_array {};
template <typename T>
static Is_pointer check_type(const T*, const T* const*);
static Is_array check_type(const void*, const void*);
};
For those who are interested, it works by inserting two "tests" before the standard sizeof-based array-size macro. Those tests don't impact the final calculation, but are designed to generate compile errors for non-array types:
The first test fails unless arr is integral, enum, pointer, or array. reinterpret_cast<const T*> should fail for any other types.
The second test fails for integral, enum, or pointer types.
Integral and enum types will fail because there's no version of check_type that they match, since check_type expects pointers.
Pointer types will fail because they'll match the templated version of check_type, but the return type (Is_pointer) for the templated check_type is incomplete, which will produce an error.
Array types will pass because taking the address of an array of type T
will give you T (*)[], aka a pointer-to-an-array, not a pointer-to-a-pointer. That means that the templated version of check_type won't match. Thanks to SFINAE, the compiler will move on to the non-templated version of check_type, which should accept any pair of pointers. Since the return type for the non-templated version is defined completely, no error will be produced. And since we're not dealing with templates now, local types work fine.
If you are on a Microsoft only platform, you can take advantage of the _countof macro. This is a non-standard extension which will return the count of elements within an array. It's advantage over most countof style macros is that it will cause a compilation error if it's used on a non-array type.
The following works just fine (VS 2008 RTM)
static int ARRAY[5];
enum ENUM{N=_countof(ARRAY)};
But once again, it's MS specific so this may not work for you.
You can't solve it in general, thats one the reasons for array wrappers like boost array (plus stl-style behaviour of course).
It appears not to be possible to obtain the sizeof array as a compile-time constant without a macro with current C++ standard (you need a function to deduce the array size, but function calls are not allowed where you need a compile-time constant). [Edit: But see Minaev's brilliant solution!]
However, your template version isn't typesafe either and suffers from the same problem as the macro: it also accepts pointers and notably arrays decayed to a pointer. When it accepts a pointer, the result of sizeof(T*) / sizeof(T) cannot be meaningful.
Better:
template <typename T, size_t N>
size_t sizeof_array(T (&)[N]){
return N;
}
Without C++0x, the closest I can get is:
#include <iostream>
template <typename T>
struct count_of_type
{
};
template <typename T, unsigned N>
struct count_of_type<T[N]>
{
enum { value = N };
};
template <typename T, unsigned N>
unsigned count_of ( const T (&) [N] )
{
return N;
};
int main ()
{
std::cout << count_of_type<int[20]>::value << std::endl;
std::cout << count_of_type<char[42]>::value << std::endl;
// std::cout << count_of_type<char*>::value << std::endl; // compile error
int foo[1234];
std::cout << count_of(foo) << std::endl;
const char* bar = "wibble";
// std::cout << count_of( bar ) << std::endl; // compile error
enum E1 { N = count_of_type<int[1234]>::value } ;
return 0;
}
which either gives you a function you can pass the variable to, or a template you can pass the type too. You can't use the function for a compile time constant, but most cases you know the type, even if only as template parameter.
Now STL libraries are available to decide/select array size compile time
#include <iostream>
#include <array>
template<class T>
void test(T t)
{
int a[std::tuple_size<T>::value]; // can be used at compile time
std::cout << std::tuple_size<T>::value << '\n';
}
int main()
{
std::array<float, 3> arr;
test(arr);
}
Output:
3