how to use explicit correctly?

Aug 9, 2010 at 10:55am
Hi

I'm trying to use explicit to prevent implicit conversions from one integral type to another - but it's not working. Is this just not possible?

If I have a constructor taking an integer, and I specify that constructor as being explicit, I would expect implicit conversions from double -> int, short -> int, char -> int to fail, but, as seen in the code below, they don't.

Why is this?
Is there any way to prevent these implicit conversions?

TIA
Steve

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>

class foo
{
    foo();
    foo(const foo&);
public:
    explicit foo(int) 
    {
        std::cout << __PRETTY_FUNCTION__ << std::endl; 
    }
};

int main()
{
    int    a = 1;    foo f_a(a);
    double b = 1.1;  foo f_b(b);
    short  c = 1;    foo f_c(c);
    char   d = '1';  foo f_d(d);
    long   e = 1L;   foo f_e(e);
    return 0;
}
Aug 9, 2010 at 12:12pm
Aug 9, 2010 at 12:25pm
So it's only to prevent implicit construction of objects through the assignment operator - it won't prevent implicit conversion of constructor arguments to match the constructor's argument types?

Aug 9, 2010 at 12:50pm
Yes.

I can think of two ways to do this though.. (Don't get me wrong, I'm not encouraging you to do this. Unless you have a very good reason..)

1.template specialization
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>

struct foo{
    //...
};

template<typename T>
foo make_foo(T i){
    std::cout << "fail\n";//you could throw an exception here
    //or maybe exit, or assert..
    return foo();
}

template<>
foo make_foo<int>(int i){
    std::cout << "win\n";
    return foo();
}

int main(){
    int i = 1;
    float f = 1;
    foo a = make_foo(i);
    foo b = make_foo(f);

    std::cin.get();
    return 0;
}


2.Or templates + typeid..
1
2
3
4
5
6
template<typename T>
foo make_foo(T i){
    if(typeid(T) == typeid(int)) std::cout << "win\n";
    else std::cout << "fail\n";
    return foo();
}


Why would you want to do this?
Aug 9, 2010 at 1:14pm
I have a constructor taking an integer.
I also have some data which I'm receiving in the form of uint8_t.
Conceptually this is an integral value with range 0 - 255
However, in c++ it's treated as an unsigned char, and doing things like passing to std::cout will print a char not an integer.

1
2
3
4
5
6
7
#include <iostream>
int main()
{
    uint8_t val = 56;
    std::cout << "val=" << val << std::endl;
    return 0;
}


output:
val=8


In a text-based API, a valid uint8_t value could be received as "134". However, if I say the following:

uint8_t val = boost::lexical_cast<uint8_t>("134");

I get an exception because lexical_cast is attempting to parse it as a char.
The following code will work without overflowing the uint8_t:

uint8_t val = boost::lexical_cast<uint16_t>("134");

Anyway, I had some other code which was failing because I was parsing the uint8_t value incorrectly. I was passing an incorrectly parsed uint8_t value to a constructor. I thought if I put explicit on the constructor I could enforce having to create an int from the uint8_t, and then pass the int to the constructor.

I realise this wouldn't have fixed the incorrect parsing of the uint8_t, but if I was able to prevent implicit conversions, I would have had a compile time error for every instance of passing my (incorrectly parsed) uint8_t value to the ctor.
Aug 10, 2010 at 7:24pm
explicit keywords used to avoid implicit conversion from constructor argument to the class object.

class foo
{
foo(int x);
};

if we don't use explicit keywords and you try assign int with object of class foo,compiler will not report an compilation error.

foo a = 3;

compiler will not give error on line a=3.

to avoid these types of error we use explicit keywords.

please go thru scott meyers books on C++ for more clarification.

Topic archived. No new replies allowed.