f



Another problem with std::set

In the following example, if I define a set in main() everything
works but if I define it, in the same way, in a struct it doesn't work.

g++ -std=c++11 Set.cpp

Thank you, (especially your patience)
Joe


======================= Set.cpp ======================
#include <iostream>
#include <set>

class X
{
private:
   int x;
public:
   X(int a) : x(a) {}
   friend bool Comp(const X &, const X &);
};

bool Comp(const X &xobj1, const X &xobj2)
{
   return xobj1.x < xobj2.x;
}

struct Y
{
   // error, Compiler says Comp is not a type, it is not a type
   // it is a function ptr since it is the name of a function
   std::set<X, bool (*)(const X &, const X &)> AnotherSetOfX(Comp);
};

int main()
{
   // works fine
   std::set<X, bool (*)(const X &, const X &)> SetOfX(Comp);
}
0
Joseph
12/23/2016 12:22:13 AM
comp.lang.c++ 49423 articles. 7 followers. Post Follow

4 Replies
533 Views

Similar Articles

[PageSpeed] 13

Joseph Hesse <joeh@gmail.com> writes:
>// error, Compiler says Comp is not a type, it is not a type
>// it is a function ptr since it is the name of a function
>std::set<X, bool (*)(const X &, const X &)> AnotherSetOfX(Comp);

  You are using an initializer in the member declaration
  in the class specifier. Such an initializer needs to be
  a braced initializer or an equals initializer. And it is
  only possible with a recent C++ at all. So, you might try,

std::set<X, bool (*)(const X &, const X &)> AnotherSetOfX{Comp};

  .

0
ram
12/23/2016 12:39:53 AM
On 23.12.2016 01:22, Joseph Hesse wrote:
> In the following example, if I define a set in main() everything
> works but if I define it, in the same way, in a struct it doesn't work.
>
> g++ -std=c++11 Set.cpp
>
> Thank you, (especially your patience)
> Joe
>
>
> ======================= Set.cpp ======================
> #include <iostream>
> #include <set>
>
> class X
> {
> private:
>   int x;
> public:
>   X(int a) : x(a) {}
>   friend bool Comp(const X &, const X &);
> };
>
> bool Comp(const X &xobj1, const X &xobj2)
> {
>   return xobj1.x < xobj2.x;
> }
>
> struct Y
> {
>   // error, Compiler says Comp is not a type, it is not a type
>   // it is a function ptr since it is the name of a function
>   std::set<X, bool (*)(const X &, const X &)> AnotherSetOfX(Comp);
> };
>
> int main()
> {
>   // works fine
>   std::set<X, bool (*)(const X &, const X &)> SetOfX(Comp);
> }

There are three ways to initialize a data member of a class type object:

     struct S{ int x{42}; };
     struct T{ int x = 42; };
     struct U{ int x; U():x{42}{} };

The last one defines a default constructor for `U`.

The two first specify a default initialization that can be overridden by 
a constructor, and if it's not overridden it is as if it was done by the 
constructor like the one in `U`.

     • • •

I assume that you're doing this for learning & language exploration.

But for practical programming just do as Mr. Flibble wrote:

define an `operator<` for the class, e.g. like this:

     struct Point
     {
         int x = 0;
         int y = 0;

         friend
         auto operator<( Point const& a, Point const& b )
             -> bool
         { return tie( a.x, a. y ) < tie( b.x, b.y ); }
     };

… where `tie` is `std::tie` from the `<tuple>` header.

     • • •

An alternative to `tie` and that kind of stuff, is to define a 
three-valued `compare` function, like `std::string::compare`, and then 
inherit from a class template that defines `<` and other relational 
operators in terms of `compare`. The inherit-in-an-implementation is 
called the Barton-Nackman trick. It's in Wikipedia and other places.

Cheers & hth.,

- Alf

0
Alf
12/23/2016 12:47:48 AM
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> writes:
>On 23.12.2016 01:22, Joseph Hesse wrote:
>>X(int a) : x(a) {}

  The above constructor might also be written
  with �explicit� to forbid implicit conversions.

>struct S{ int x{42}; };
>The two first specify a default initialization that can be overridden by 
>a constructor

  And, it seems (I only tried it with an implementation),
  also with am aggregate initializer by the client.
  (The execution shows that the in-class initializer of
  the class �pair� is not used.)

#include <iostream>
#include <ostream>
#include <string>

using namespace ::std::literals;

template< class C >
C value( C const x )
{ ::std::cout << "value: "s << x << '\n'; 
  return x; }

struct pair
{ double b{ value( 1.0 ) }; };

int main()
{ pair o{ value( 2.0 ) };
  ::std::cout << o.b << '\n'; }

  transcript

value: 2
2

0
ram
12/23/2016 12:54:37 AM
On 2016-12-23 01:22, Joseph Hesse wrote:
> In the following example, if I define a set in main() everything
> works but if I define it, in the same way, in a struct it doesn't work.
>
> g++ -std=c++11 Set.cpp
>
> Thank you, (especially your patience)
> Joe
>
>
> ======================= Set.cpp ======================
> #include <iostream>
> #include <set>
>
> class X
> {
> private:
>   int x;
> public:
>   X(int a) : x(a) {}
>   friend bool Comp(const X &, const X &);
> };
>
> bool Comp(const X &xobj1, const X &xobj2)
> {
>   return xobj1.x < xobj2.x;
> }
>
> struct Y
> {
>   // error, Compiler says Comp is not a type, it is not a type
>   // it is a function ptr since it is the name of a function
>   std::set<X, bool (*)(const X &, const X &)> AnotherSetOfX(Comp);
> };

If Comp had been a type, AnotherSetOfX(Comp); would have declared a 
function taking a Comp parameter and returning a set.

The syntax for member initializations was deliberatly designed so that 
it could not be confused with declaring a function. So you can only use 
= Comp or {Comp}, but not (Comp).


     Bo Persson


0
Bo
12/23/2016 6:27:51 PM
Reply: