End-of-the-week fun

Discussion in 'C++' started by Dave, Nov 8, 2003.

  1. Dave

    Dave Guest

    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;
    }
    Dave, Nov 8, 2003
    #1
    1. Advertising

  2. Dave wrote:
    > 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,


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


    but surely item 2 does. I'd be very interested to
    > hear the reason for this behavior if anybody knows...


    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.


    >
    > #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, Nov 8, 2003
    #2
    1. Advertising

  3. Dave wrote in news::

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


    #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.
    --
    http://www.victim-prime.dsl.pipex.com/
    Rob Williscroft, Nov 8, 2003
    #3
  4. Dave wrote:
    > 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.


    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
    Andrey Tarasevich, Nov 8, 2003
    #4
  5. Dave

    Dave Guest

    "Andrey Tarasevich" <> wrote in message
    news:...
    > Dave wrote:
    > > 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.

    >
    > 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*'
    >


    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!

    > 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
    >
    Dave, Nov 8, 2003
    #5
  6. Dave wrote:
    >>...
    >> 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*'
    >>

    >
    > 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!


    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
    Andrey Tarasevich, Nov 8, 2003
    #6
  7. > ...
    > [1 - 5 skipped]
    > ...


    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
    Andrey Tarasevich, Nov 8, 2003
    #7
  8. Dave

    Rolf Magnus Guest

    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.
    Rolf Magnus, Nov 8, 2003
    #8
  9. Dave

    Moonlit Guest

    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" <> wrote in message
    news:...
    > 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;
    > }
    >
    >
    Moonlit, Nov 8, 2003
    #9
  10. Dave

    Agent Mulder Guest

    <Dave>
    > TGIF!!!
    > What are some of the most obscure features of the language you know of?

    </>

    Let the compiler do computations. The compiler:

    #include<iostream>

    template<int A>struct Factorial
    {
    enum{value=A*Factorial<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
    Agent Mulder, Nov 8, 2003
    #10
  11. Dave

    Dave Guest

    > 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.


    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(const std::bitset<N> &bs)
    {
    std::cout << bs.template to_string<char, char_traits<char>,
    allocator<char> >();
    // std::cout << bs.to_string<char, char_traits<char>, allocator<char>
    >(); // This won't work!

    }

    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!
    Dave, Nov 8, 2003
    #11
  12. Dave

    Dave Guest

    > 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!


    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::~base()" << endl;}
    virtual void virt_func() {cout << "base::virt_func()" << endl;}
    };

    class derived: protected base
    {
    public:
    derived() {cout << "derived::derived()" << endl;}
    virtual ~derived() {cout << "derived::~derived()" << 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;
    }
    Dave, Nov 18, 2003
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Guest
    Replies:
    3
    Views:
    1,827
    Alexandre
    Dec 22, 2003
  2. richard
    Replies:
    0
    Views:
    260
    richard
    Mar 19, 2006
  3. Guest
    Replies:
    3
    Views:
    516
    Alexandre
    Dec 22, 2003
  4. Guest
    Replies:
    3
    Views:
    1,073
    Alexandre
    Dec 22, 2003
  5. SimonC
    Replies:
    13
    Views:
    326
    Dr John Stockton
    Jan 4, 2005
Loading...

Share This Page