Little things

1) int i=5; or int i(5);?
2) unsigned char maxc = '\xFF'; or
unsigned char maxc = UCHAR_MAX; or
unsigned char maxc = std::numeric_limits<unsigned char>::max();?
3) int main() {} or int main() {return 0;}?
std::numeric_limits<> of course.

For one I don't have to remember the names of a bunch of manifest constants - one for each type.

Two, std::numeric_limits<T> is polymorphic - try writing std::numeric_limits<T>::max() where T is a template parameter using any of the other constructs.

Three, '\xFF' gives a constant of the wrong type; UCHAR_MAX may (usually does) - the standard does not require that the type of UCHAR_MAX must be an unsigned char.

1
2
3
4
5
6
7
8
void foo( int ) { std::cout << "overload for int\n" ; }
void foo( unsigned char ) { std::cout << "overload for unsigned char\n" ; }

int main()
{
        foo( UCHAR_MAX ) ; // could resolve to foo(int) or be ambiguous
        foo( std::numeric_limits<unsigned char>::max() ) ; // foo( unsigned char )
}



In addition, unsigned char maxc = '\xFF'; is not portable.
Bump.
Thank you for your reply JLBorges, bringing up things I didn't think of.
However, I'm also interested in answers for 1) and 3).
for 1:
I'd say that

int i=5;

is the only true answer. I do only use this, actually...

for 3:
If you declare a function as an integer-returning one, you have to enter a return value. So

int main() {return 0;}

is right, the other one not. The compiler would also complain about this solution. ^^
Last edited on
For 1, I'm pretty sure they are both equivalent. Using = while declaring a variable will invoke the appropriate constructor.

For 3, they are also equivalent. main() alone is allowed to not explicitly return a value and it will automatically return 0.
> 1) int i=5; or int i(5);?

I have no strong preference about this, as long as the code is consistent about using either one or the other.

I personally use int i = 5 ; for this reason:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <string>

// default constructible, provides for implicit conversion to std::string
struct A { /*...*/ operator std::string() const ; } ;

int main()
{
    // str_one is a string initialized with a default construted A
    std::string str_one = A() ;
    auto sz = str_one.size() ;

    // what is str_two here?
    std::string str_two( A() ) ;
    //sz = str_two.size() ; // *** error, str_two is a function ***

    // str_three is a string initialized with a default construted A
    std::string str_three( ( A() ) ) ; // but this seems ungainly to my eyes
    sz = str_three.size() ;
}




> 3) int main() {} or int main() {return 0;}

Again, I have no strong preference about this.

I omit return 0 ; if main has only one return at the end. Otherwise, I tend to put it in.



> I'd say that int i=5; is the only true answer. I do only use this, actually...

Hmm.. Fair enough if you are initializing an int, but ...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
struct A { /*...*/ } ; // default constructible

struct B { explicit B(A) ;  /* .. */ } ;

int main()
{
    // TODO: initialize an object of type B with a default constructed A
    
    // B try_one = A() ; // *** error, no implicit conversion from A to B
    
    B try_two( A() ) ; // compiles, but we are declaring a function,
    
    B try_three( ( A() ) ) ; // fine
    
    // B try_four( { A() } ) ; // *** error, no implicit conversion from A to B

    A lvalue;
    B try_five = lvalue ; // compiles, but we have had to create an unnecessary l-value

   // ...
}
Last edited on
Topic archived. No new replies allowed.