Hi Mike,
This problem intrigued me enough that I felt like actually doing the
work to make sense of it - which turned out to be a useful learning
experience, as I now:
(a) better understand the typename keyword, and
(b) realise how amazingly helpful the Clang C++ compiler output can be. :)
Short explanation - I think you did at least three things wrong:
1. you used the "typename" keyword incorrectly,
2. you defined the SortByName functor class incorrectly (inheriting
from std::binary_function when the operator() was _not_ a binary
function), then
3. you *used* the SortByName functor incorrectly (by supplying it to
std::list::sort, which expects a 2-arg function instead of 3-arg).
Longer explanation below:
On 06/11 02:04:57, Mike Douglass wrote:
I'm trying to sort a list of edge_descriptors, but I get the
compiler error described below.
[ ... ]
//With the above line uncommented the compiler says:
/*
./Includes/Utilities.cpp: In function ???void Sort_Test(Graph&)???:
./Includes/Utilities.cpp:539: error: wrong number of template arguments (1,
should be 2)
./Includes/Utilities.cpp:513: error: provided for ???template struct SortByName???
make: *** [plc] Error 1
*/
[ ... ]
But clearly there are two template arguments - < typename Graph,
typename edgeDescriptor >
(Note: I rewrote your code into a bastardised form that doesn't use
Boost::Graph, as the problem doesn't look like it's got anything to do
with that.)
Compile the attached douglass-broken.cpp with GNU g++ and you get
error output closely matching your report (I've replaced GCC's open/close
single-quotes with ' to avoid encoding issues):
----------------------------------------------------------------------
$ g++ douglass-broken.cpp -o douglas-broken
douglass-broken.cpp: In function 'void Sort_Test(Graph&)':
douglass-broken.cpp:45:62: error: wrong number of template arguments (1, should be 2)
douglass-broken.cpp:21:8: error: provided for 'template struct SortByName'
$
----------------------------------------------------------------------
I agree, it's not a particuarly helpful error message - in fact it's
outright misleading.
The output from clang++, however, is *extremely* helpful (though it's
much easier to read with the default coloured/bolded output, here it's
just plain text):
----------------------------------------------------------------------
$ clang++ douglass-broken.cpp -o douglass-broken
douglass-broken.cpp:45:32: error: expected a qualified name after 'typename'
A.sort(SortByName());
^
douglass-broken.cpp:45:48: error: expected a qualified name after 'typename'
A.sort(SortByName());
^
In file included from douglass-broken.cpp:2:
In file included from /usr/include/c++/4.5.1/list:65:
/usr/include/c++/4.5.1/bits/list.tcc:286:12: error: no matching function for call to object of type
'SortByName,
std::allocator > >, std::basic_string<char> >'
if (__comp(*__first2, *__first1))
^~~~~~
/usr/include/c++/4.5.1/bits/list.tcc:398:7: note: in instantiation of function template specialization 'std::list >::merge, std::allocator > >, std::basic_string<char> > >'
requested here
__counter->merge(__carry, __comp);
^
douglass-broken.cpp:45:5: note: in instantiation of function template specialization 'std::list >::sort, std::allocator > >, std::basic_string<char> > >' requested here
A.sort(SortByName());
^
douglass-broken.cpp:64:5: note: in instantiation of function template specialization 'Sort_Test, std::allocator > > >' requested here
Sort_Test<Graph>(the_graph);
^
douglass-broken.cpp:23:10: note: candidate function not viable: requires 3 arguments, but 2 were provided
bool operator()(const Graph& g, const edgeDescriptor& a, const edgeDescriptor& b)
^
3 errors generated.
----------------------------------------------------------------------
So, the first problem is that you used typename where it shouldn't be
used, in this line:
A.sort(SortByName());
...and I suspect that confused the g++ parser so that it interpreted
the expression "typename Graph, typename edgeDescriptor" as a *single*
type, resulting in the confusing error message.
You can verify this by adding extra nonsense types in the same way, eg.:
A.sort(SortByName());
Compile that and the error message supplied by my g++ (I'm using
version 4.5.1) is still the same "wrong number of template arguments
(1, should be 2)", despite it now looking like *five* arguments :).
As you can see, the Clang C++ compiler does a much better job, both
pointing out the typename-usage error *and* reporting (albeit
indirectly) that you're supplying a three-argument functor to the
std::list::sort, when it actually requires a binary functor/function.
(Note: To be fair to GCC, once you remove the two incorrect "typename"
keywords in the A.sort line, it also generates a usable error message.)
One way to fix it would be as Cedric suggested, and that's the model I
used in my douglass-working.cpp (attached). I changed SortByName so it
requires a const Graph& in its constructor, stores a reference to that
in a private variable, *then* changed SortByName::operator() to take
two edgeDescriptor args and return bool.
It is dicey in one way, in that it stores a *reference* to its Graph -
so if the SortByName object outlives the Graph then it could blow up
spectacularly. But the alternative of copying the entire graph seemed
a bit excessive.
Another way to fix it (and also avoid the reference-storing problem)
requires using Boost::Bind - change SortByName to this:
----------------------------------------------------------------------
template
struct SortByName
{
typedef bool result_type; // required for use by STL algorithms.
result_type operator()(G& g, const ED& a, const ED& b)
{
return g[a].eName < g[b].eName;
}
};
----------------------------------------------------------------------
...and the A.sort call to this:
A.sort( boost::bind(SortByName(), g, _1, _2) );
That seems to work fine, and may be a closer match to what you
originally intended.
Pete.
--
"DAMN WHO MESSED WITH MY CAPSLOCK KEY that's better."
-- geoff lane, , asr