End-of-the-week fun

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Dave

    End-of-the-week fun

    TGIF!!!

    I don't know if people will be interested in this or not, but if so, we
    might learn a few interesting tidbits!

    What are some of the most obscure features of the language you know of?
    Please exclude anything that's not strictly part of the standard, even if a
    very common extension. This can be in the core language itself or in the
    standard library.

    In addition to the obscure feature, a reason for its existence, if known,
    would also be very interesting to hear!

    I'll throw out a couple:

    1. Constructor and destructor names may be surrounded by parenthesis. i.e.
    (~MyClass)( ) {...}

    2. When trying to match an exception to a catch clause, user-defined
    conversions via a one-argument constructor are not used. The short program
    below prints "Point 2".

    Unfortunately, I don't know the reasons for these. Item 1 may not have a
    real compelling reason, but surely item 2 does. I'd be very interested to
    hear the reason for this behavior if anybody knows...

    #include <iostream>

    using namespace std;

    class foo_t
    {
    public:
    foo_t(int) {}
    (~foo_t)() {}
    };

    int main()
    {
    try
    {
    throw 45;
    }
    catch(foo_t)
    {
    cout << "Point 1" << endl;
    }
    catch(int)
    {
    cout << "Point 2" << endl;
    }

    return 0;
    }


  • Gianni Mariani

    #2
    Re: End-of-the-week fun

    Dave wrote:[color=blue]
    > TGIF!!!
    >
    > I don't know if people will be interested in this or not, but if so, we
    > might learn a few interesting tidbits!
    >
    > What are some of the most obscure features of the language you know of?
    > Please exclude anything that's not strictly part of the standard, even if a
    > very common extension. This can be in the core language itself or in the
    > standard library.
    >
    > In addition to the obscure feature, a reason for its existence, if known,
    > would also be very interesting to hear!
    >
    > I'll throw out a couple:
    >
    > 1. Constructor and destructor names may be surrounded by parenthesis. i.e.
    > (~MyClass)( ) {...}
    >
    > 2. When trying to match an exception to a catch clause, user-defined
    > conversions via a one-argument constructor are not used. The short program
    > below prints "Point 2".
    >
    > Unfortunately, I don't know the reasons for these. Item 1 may not have a
    > real compelling reason,[/color]

    Maybe it makes ut easier to parse templates (not even thought out idea)


    but surely item 2 does. I'd be very interested to[color=blue]
    > hear the reason for this behavior if anybody knows...[/color]

    This one is (I think) obvious.

    consider this code.

    try
    {
    polyobj->VirtFunc();

    }
    catch ( foo_t )
    {
    }
    catch ( int )
    {
    }

    Since the compiler has no idea what might get thrown
    there is no way it will know which conversion funtion
    to use - and some of the conversions may become
    ambigous (at run-time) since there may be more
    than one conversion and that's simply a bad idea.

    [color=blue]
    >
    > #include <iostream>
    >
    > using namespace std;
    >
    > class foo_t
    > {
    > public:
    > foo_t(int) {}
    > (~foo_t)() {}
    > };
    >
    > int main()
    > {
    > try
    > {
    > throw 45;
    > }
    > catch(foo_t)
    > {
    > cout << "Point 1" << endl;
    > }
    > catch(int)
    > {
    > cout << "Point 2" << endl;
    > }
    >
    > return 0;
    > }
    >
    >[/color]

    Comment

    • Rob Williscroft

      #3
      Re: End-of-the-week fun

      Dave wrote in news:vqof847v9o mbcc@news.super news.com:
      [color=blue]
      > 1. Constructor and destructor names may be surrounded by parenthesis.
      > i.e. (~MyClass)( ) {...}
      >[/color]

      #include <iostream>
      #include <ostream>

      #define macro(x) (std::cout << (x) << std::endl)

      void (macro)( char const * x )
      {
      macro( x );
      }

      int (f(int i ))
      {
      return i + 1;
      }

      char const (*name) = "name";

      int main()
      {
      using namespace std;

      macro( f( 2 ) );
      macro( "macro" );
      #undef macro
      macro( "function" );
      macro( name );
      }

      Rob.
      --

      Comment

      • Andrey Tarasevich

        #4
        Re: End-of-the-week fun

        Dave wrote:[color=blue]
        > TGIF!!!
        >
        > I don't know if people will be interested in this or not, but if so, we
        > might learn a few interesting tidbits!
        >
        > What are some of the most obscure features of the language you know of?
        > Please exclude anything that's not strictly part of the standard, even if a
        > very common extension. This can be in the core language itself or in the
        > standard library.
        >
        > In addition to the obscure feature, a reason for its existence, if known,
        > would also be very interesting to hear!
        >
        > I'll throw out a couple:
        >
        > 1. Constructor and destructor names may be surrounded by parenthesis. i.e.
        > (~MyClass)( ) {...}
        >
        > 2. When trying to match an exception to a catch clause, user-defined
        > conversions via a one-argument constructor are not used.[/color]

        3. Normally in both C and C++ declaring an entity as 'int' is equivalent
        to declaring it as 'signed int'. However, there is a context in both C
        and C++ where 'int' might be equivalent to 'unsigned int'
        (implementation defined). This context is: bit field declarations

        struct S {
        int i:5; // <- signed or unsigned - implementation defined
        };

        4. There is a context in C++ where parenthesis changes the semantical
        meaning of an expression even though it doesn't alter the binding of
        operators (defined by their precedence). This context is: taking the
        address of a class data member

        struct S {
        int i;
        };
        ...
        &S::i; // <- this expression has type 'int (S::*)'
        &(S::i); // <- this expression has type 'int*'

        5. In constructor initializer lists data member names and their
        respective initializers are looked up in different scopes, so that
        there's no conflict between constructor parameter names and class data
        member names

        struct S {
        int i;
        S(int i) : i(i) // initializes ' ' with value of parameter 'i'
        {}
        };

        --
        Best regards,
        Andrey Tarasevich

        Comment

        • Dave

          #5
          Re: End-of-the-week fun


          "Andrey Tarasevich" <andreytarasevi ch@hotmail.com> wrote in message
          news:vqoj001tah gb56@news.super news.com...[color=blue]
          > Dave wrote:[color=green]
          > > TGIF!!!
          > >
          > > I don't know if people will be interested in this or not, but if so, we
          > > might learn a few interesting tidbits!
          > >
          > > What are some of the most obscure features of the language you know of?
          > > Please exclude anything that's not strictly part of the standard, even[/color][/color]
          if a[color=blue][color=green]
          > > very common extension. This can be in the core language itself or in[/color][/color]
          the[color=blue][color=green]
          > > standard library.
          > >
          > > In addition to the obscure feature, a reason for its existence, if[/color][/color]
          known,[color=blue][color=green]
          > > would also be very interesting to hear!
          > >
          > > I'll throw out a couple:
          > >
          > > 1. Constructor and destructor names may be surrounded by parenthesis.[/color][/color]
          i.e.[color=blue][color=green]
          > > (~MyClass)( ) {...}
          > >
          > > 2. When trying to match an exception to a catch clause, user-defined
          > > conversions via a one-argument constructor are not used.[/color]
          >
          > 3. Normally in both C and C++ declaring an entity as 'int' is equivalent
          > to declaring it as 'signed int'. However, there is a context in both C
          > and C++ where 'int' might be equivalent to 'unsigned int'
          > (implementation defined). This context is: bit field declarations
          >
          > struct S {
          > int i:5; // <- signed or unsigned - implementation defined
          > };
          >
          > 4. There is a context in C++ where parenthesis changes the semantical
          > meaning of an expression even though it doesn't alter the binding of
          > operators (defined by their precedence). This context is: taking the
          > address of a class data member
          >
          > struct S {
          > int i;
          > };
          > ...
          > &S::i; // <- this expression has type 'int (S::*)'
          > &(S::i); // <- this expression has type 'int*'
          >[/color]

          Interesting! The first expression has type pointer-to-member, but I'm
          curious what an example is of how an expression of the second type would be
          used... My compiler(VC++ 7.1) seems to choke on it!
          [color=blue]
          > 5. In constructor initializer lists data member names and their
          > respective initializers are looked up in different scopes, so that
          > there's no conflict between constructor parameter names and class data
          > member names
          >
          > struct S {
          > int i;
          > S(int i) : i(i) // initializes ' ' with value of parameter 'i'
          > {}
          > };
          >
          > --
          > Best regards,
          > Andrey Tarasevich
          >[/color]


          Comment

          • Andrey Tarasevich

            #6
            Re: End-of-the-week fun

            Dave wrote:[color=blue][color=green]
            >>...
            >> 4. There is a context in C++ where parenthesis changes the semantical
            >> meaning of an expression even though it doesn't alter the binding of
            >> operators (defined by their precedence). This context is: taking the
            >> address of a class data member
            >>
            >> struct S {
            >> int i;
            >> };
            >> ...
            >> &S::i; // <- this expression has type 'int (S::*)'
            >> &(S::i); // <- this expression has type 'int*'
            >>[/color]
            >
            > Interesting! The first expression has type pointer-to-member, but I'm
            > curious what an example is of how an expression of the second type would be
            > used... My compiler(VC++ 7.1) seems to choke on it![/color]

            The example I used is far from perfect. Sorry. In order to demonstrate
            the difference I should have used a context where both expressions are valid

            struct S {
            int i;

            void foo()
            {
            &S::i; // <- this expression has type 'int (S::*)'
            &(S::i); // <- this expression has type 'int*'
            }
            };

            --
            Best regards,
            Andrey Tarasevich

            Comment

            • Andrey Tarasevich

              #7
              Re: End-of-the-week fun

              > ...[color=blue]
              > [1 - 5 skipped]
              > ...[/color]

              6. (This is straight from the standard and might be well known to some,
              but anyway) Typedef names for function types can be used to declare both
              regular and member functions

              typedef void VVF();

              VVF foo; // declares 'void foo()'

              struct S
              {
              VVF bar; // declares 'void S::bar()'
              };

              Moreover, const-qualifier can be added to 'typedef'-ed type and used in
              the following manner

              typedef void VVFC() const;

              struct S
              {
              VVFC bar(); // declares 'void bar() const'
              };

              This typedef-name cannot be used to declare non-member functions.

              7. In most cases the type and value of the initializer expression in a
              declaration does not depend on the type of the object being declared. In
              a popular example

              double d = 1/2;

              the type of the expression '1/2' is 'int' and its value is '0', not
              'double' and '0.5'. However, in certain contexts the type and value of
              the expression might depend on the type of the object being initialized:

              void foo();
              void foo(int);

              void (*p1)() = &foo;
              // The initializer expression has type 'void (*)()' and it points
              // to the first 'foo'

              void (*p2)(int) = &foo; // the initializer has type 'void (*)(int)'
              // The initializer expression has type 'void (*)(int)' and it points
              // to the second 'foo'

              The same applies to assignment and some other contexts.

              --
              Best regards,
              Andrey Tarasevich

              Comment

              • Rolf Magnus

                #8
                Re: End-of-the-week fun

                Andrey Tarasevich wrote:

                [1 - 7 skipped]

                8. Standard library: The standard class basic_ios provides a conversion
                operator to void* that returns "some non-null pointer" (quoted from the
                standard) if it's not in fail state or a null pointer if it is. It is
                e.g. used in the famous:

                while (input_stream >> some_variable)
                {
                // do something
                }

                There, operator>> returns a reference to the stream, which is then
                converted to void* for the loop condition.

                Comment

                • Moonlit

                  #9
                  Re: End-of-the-week fun

                  Hi,

                  Sswapping the array name and the subscript:

                  #include <iostream>

                  using namespace std;

                  int main()
                  {
                  char A[6];

                  memset( A, 0, sizeof A );
                  A[5] = 'I' ;
                  cerr << 5[A] << endl;

                  return 0;
                  }

                  Regards, Ron AF Greve



                  "Dave" <better_cs_now@ yahoo.com> wrote in message
                  news:vqof847v9o mbcc@news.super news.com...[color=blue]
                  > TGIF!!!
                  >
                  > I don't know if people will be interested in this or not, but if so, we
                  > might learn a few interesting tidbits!
                  >
                  > What are some of the most obscure features of the language you know of?
                  > Please exclude anything that's not strictly part of the standard, even if[/color]
                  a[color=blue]
                  > very common extension. This can be in the core language itself or in the
                  > standard library.
                  >
                  > In addition to the obscure feature, a reason for its existence, if known,
                  > would also be very interesting to hear!
                  >
                  > I'll throw out a couple:
                  >
                  > 1. Constructor and destructor names may be surrounded by parenthesis.[/color]
                  i.e.[color=blue]
                  > (~MyClass)( ) {...}
                  >
                  > 2. When trying to match an exception to a catch clause, user-defined
                  > conversions via a one-argument constructor are not used. The short[/color]
                  program[color=blue]
                  > below prints "Point 2".
                  >
                  > Unfortunately, I don't know the reasons for these. Item 1 may not have a
                  > real compelling reason, but surely item 2 does. I'd be very interested to
                  > hear the reason for this behavior if anybody knows...
                  >
                  > #include <iostream>
                  >
                  > using namespace std;
                  >
                  > class foo_t
                  > {
                  > public:
                  > foo_t(int) {}
                  > (~foo_t)() {}
                  > };
                  >
                  > int main()
                  > {
                  > try
                  > {
                  > throw 45;
                  > }
                  > catch(foo_t)
                  > {
                  > cout << "Point 1" << endl;
                  > }
                  > catch(int)
                  > {
                  > cout << "Point 2" << endl;
                  > }
                  >
                  > return 0;
                  > }
                  >
                  >[/color]


                  Comment

                  • Agent Mulder

                    #10
                    Re: End-of-the-week fun

                    <Dave>[color=blue]
                    > TGIF!!!
                    > What are some of the most obscure features of the language you know of?[/color]
                    </>

                    Let the compiler do computations. The compiler:

                    #include<iostre am>

                    template<int A>struct Factorial
                    {
                    enum{value=A*Fa ctorial<A-1>::value};
                    };

                    struct Factorial<1>
                    {
                    enum{value=1};
                    };

                    int main()
                    {
                    Factorial<6>f;
                    cout<<f.value; //output 720 computed at compile time
                    return 0;
                    }

                    -X


                    Comment

                    • Dave

                      #11
                      Re: End-of-the-week fun

                      > I don't know if people will be interested in this or not, but if so, we[color=blue]
                      > might learn a few interesting tidbits!
                      >
                      > What are some of the most obscure features of the language you know of?
                      > Please exclude anything that's not strictly part of the standard, even if[/color]
                      a[color=blue]
                      > very common extension. This can be in the core language itself or in the
                      > standard library.
                      >
                      > In addition to the obscure feature, a reason for its existence, if known,
                      > would also be very interesting to hear!
                      >
                      > I'll throw out a couple:
                      >
                      > 1. Constructor and destructor names may be surrounded by parenthesis.[/color]
                      i.e.[color=blue]
                      > (~MyClass)( ) {...}
                      >
                      > 2. When trying to match an exception to a catch clause, user-defined
                      > conversions via a one-argument constructor are not used.[/color]

                      Another interesting item just occurred to me...

                      The example of what I'm about to mention is adapted from "C++ Templates, The
                      Complete Guide", bottom of page 44.

                      The class template std::bitset<> has a member function template named
                      to_string<>(). Consider this example of using this member function
                      template:

                      template<int N>
                      void printBitSet(con st std::bitset<N> &bs)
                      {
                      std::cout << bs.template to_string<char, char_traits<cha r>,
                      allocator<char> >();
                      // std::cout << bs.to_string<ch ar, char_traits<cha r>, allocator<char>[color=blue]
                      >(); // This won't work![/color]
                      }

                      The .template is necessary to tell the compiler that to_string is a
                      template. This is analagous to using typename to tell the compiler you're
                      specifying a type name. .template and typename are necessary when the
                      construct involved depends on a template parameter (in this case N).

                      Thanks for all of the interesting responses to my original post! Keep 'em
                      coming if more comes to mind!


                      Comment

                      • Dave

                        #12
                        Re: End-of-the-week fun

                        > I don't know if people will be interested in this or not, but if so, we[color=blue]
                        > might learn a few interesting tidbits!
                        >
                        > What are some of the most obscure features of the language you know of?
                        > Please exclude anything that's not strictly part of the standard, even if[/color]
                        a[color=blue]
                        > very common extension. This can be in the core language itself or in the
                        > standard library.
                        >
                        > In addition to the obscure feature, a reason for its existence, if known,
                        > would also be very interesting to hear![/color]

                        Using protected inheritance to allow in-class polymorphism to be accessed
                        from a derived class:



                        #include <iostream>

                        using namespace std;

                        class base
                        {
                        public:
                        base() {cout << "base::base ()" << endl;}
                        virtual ~base() {cout << "base::~bas e()" << endl;}
                        virtual void virt_func() {cout << "base::virt_fun c()" << endl;}
                        };

                        class derived: protected base
                        {
                        public:
                        derived() {cout << "derived::deriv ed()" << endl;}
                        virtual ~derived() {cout << "derived::~deri ved()" << endl;}
                        virtual void virt_func() {cout << "derived::virt_ func()" << endl;}
                        };

                        class most_derived: private derived
                        {
                        public:
                        most_derived() {cout << "most_derived:: most_derived()" << endl;}
                        virtual ~most_derived() {cout << "most_derived:: ~most_derived() " <<
                        endl;}

                        void foo()
                        {
                        base *b(new derived);

                        b->virt_func();

                        delete b;
                        }
                        };

                        int main()
                        {
                        most_derived md;

                        md.foo();

                        return 0;
                        }


                        Comment

                        Working...