Error compiling a template in Sun Studio 12

We are switching to Sun Studio 12.1 and with the new compiler [CC: Sun C ++ 5.10 SunOS_sparc 2009/06/03]. I get a compilation error when compiling code that was compiled in an earlier version of Sun Compiler [CC: Sun WorkShop 6 update 2 C ++ 5.3 2001/05/15].

This is a compilation error that I am getting.

"Sample.cc": Error: could not find a match for LoopThrough (int [2]) needed in main (). 1 Error (s) detected. *** Error code 1.

THE 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 the generic version, the code compiles and the generic version is generated. I do not see this problem with MSVC 2010 with extensions disabled and the same case with ideone here . A specialized version of the function is called. Now the question is, is this a bug in Sun Compiler?

If so, how can we send an error report?

+6
source share
2 answers

In this case, the compiler does not comply with the standard and is an error. Let's look at the relevant sections.

First of 13.3 / 3 we have:

...

- Firstly, a subset of candidate functions - those that have the correct number of arguments and fulfillment of some other conditions - selected to form a set of viable functions (13.3.2).

- then the best viable function is selected on the basis of implicit (13.3.3.1), necessary to compare each argument with the corresponding parameter of each viable function.

Thus, 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 an implicit conversion sequence that converts the ith argument in the list to the type of the ith parameter of the viable function F. 13.3.3.1 determines the implicit conversion sequences and 13.3.3.2 determines what means that one implicit conversion sequence is the best sequence conversion rate or worse conversion sequence than another

Then we have

Given these definitions, a viable function F1 is defined as better than another viable function F2, if for all arguments i, ICSi (F1) is no worse than the transformation scheme than ICSi (F2), and then

- for some argument j, ICSj (F1) is a better conversion sequence than ICSj (F2), or, if it is not,

- F1 is an asymmetric function, and F2 is a template specialization or, if not this,

- F1 and F2 are functions of the template, and the function template for F1 is more specialized than the template for F2 according to the partial ordering of the rules described in 14.5.5.2, or, if not this,

Two functions are equal for the first rule (adding a constant), and the second rule does not apply (both are templates). So, we move on to the third rule. From 14.5.5.2 (which I will indicate upon request) we learn that the version of the const int function is more specialized than the version of const Item , so the best match is the const int overload, which should then be called.

The best interim fix is ​​probably the second overload:

 template<size_t SZ> void LoopThrough(int (&Item)[SZ]) { LoopThrough(static_cast<const int (&)[SZ]>(Item)); } 
+2
source

Your compiler is faulty. Both overloads have template arguments, and overload resolution should choose the most specialized one. So, besides getting a new compiler, what can you do?

First, it’s useful to understand that - even with the appropriate compilers - it is usually not a good idea to have different function template overloads. See Paragraph 66 of the C ++ Coding Standards: 101 Rules, Recommendations and Recommendations of Herb Sutter and Andrei Alexandrescu.

Fortunately, this item also offers a possible fix. All you have to do is define a template for one function and allow this function template to delegate the work to the function object of the class template. Then you can partially highlight 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 include a call to the function object and will optimize the temporary one completely. Hopefully your compiler will also do the partial specialization of class templates correctly.

Conclusion on Ideone

+1
source

Source: https://habr.com/ru/post/919507/


All Articles