Question

I have two questions about the code below:

why version / * 1 * / compiles under g++ and version / * 2 * / not?

why this code does not compile in clang?

I know How to fix it. but I want to understand why it does not work.

#include <boost/test/unit_test.hpp>

template<typename T,typename Cmp>
class queue{
public:
    queue(Cmp c):cmp(c){};
    void push(T a){
        cmp(a,a);
    }
    Cmp cmp;

};

template<typename T>
void fun(T a){
    class decreasing_order
    {
    public:
        decreasing_order(std::vector<T>  BBB):AAA(BBB) {}
        std::vector<T>  AAA;
        bool operator() (const T & lhs, const T & rhs) const
        {
            return AAA[lhs]<AAA[rhs];
        }
    };
    std::vector<T> tab;
    queue<T,  decreasing_order >uncoveredSetQueue((decreasing_order(tab)));/*1*/
 // queue<T,  decreasing_order >uncoveredSetQueue( decreasing_order(tab) );/*2*/
    uncoveredSetQueue.push(a);

}

BOOST_AUTO_TEST_CASE(TestX) {
    fun(1);
}

In clang i got the following error:

test.cpp:25:20: error: 
      'fun(int)::decreasing_order::operator()(const int &, const int
      &)::decreasing_order::AAA' is not a member of class 'const
      decreasing_order'
            return AAA[lhs]<AAA[rhs];
                   ^
/home/piotr/git/paal/test/greedy/test.cpp:10:9: note: in instantiation of
      member function 'fun(int)::decreasing_order::operator()' requested
      here
        cmp(a,a);
        ^
/home/piotr/git/paal/test/greedy/test.cpp:30:23: note: in instantiation
      of member function 'queue<int, decreasing_order>::push' requested
      here
    uncoveredSetQueue.push(a);
                  ^
/home/piotr/git/paal/test/greedy/test.cpp:35:5: note: in instantiation of
      function template specialization 'fun<int>' requested here
    fun(1);
    ^
1 error generated.

I using g++ 4.8.1 and clang 3.4-1.

Was it helpful?

Solution

queue<T,  decreasing_order >uncoveredSetQueue( decreasing_order(tab) );/*2*/

is an example of the Most Vexing Parse: it declares a function named uncoveredSetQueue which takes an argument (here named tab) of type decreasing_order and returning queue<T, decreasing_order>. As you found, adding parentheses avoids the Most Vexing Parse. You could also replace the parentheses with {} to use uniform initialization syntax.

The clang error message looks like a compiler bug to me. Most likely it doesn't correctly handle some consequences of using a local type as a template parameter (which was not allowed in C++03, and is a new C++11 feature).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top