I don't know of a compiler that provides such a flag (though it's always possible I've missed one).
Lacking it, you could build a little template that will make such implicit conversions impossible in at least a few obvious situations:
#include <cstdint>
#include <iostream>
using ::std::int32_t;
using ::std::uint32_t;
template <class T>
class holder {
T value;
public:
holder(T value) : value(value) {}
operator T&() { return value; }
operator T() const { return value; }
holder &operator=(holder const &other) { value = other.value; return *this; }
};
int main(int argc, char *argv[]) {
holder<int32_t> x = 9;
holder<uint32_t> i = x;
++i;
std::cout << " " << x << " " << i << "\n";
}
Attempting to compile with g++ gives:
trash9.cpp:20:23: error: conversion from 'holder<int>' to non-scalar type 'holder<unsigned int>' requested
holder<uint32_t> i = x;
^
If, however, we change the second to holder<int32_t> i = x;
it all works fine and acts as expected.
This suffices for the demo code you've given, but won't work in all situations. In particular, an implicit conversion in the course of evaluating an expression will still be allowed:
void use(holder<uint32_t> v) {
std::cout << v;
}
int main(int argc, char *argv[]) {
holder<int32_t> x = 9;
holder<int32_t> i = x;
use(i | 1u);
}
If you want to prevent conversions in cases like that as well, you can do it, but it's going to be a lot more work--you'll need to remove the operator T
and operator T&
from the code above, and then implement all the operators you do want to support. That would/will probably be tedious to the point that it's at least mildly painful, but you might find it acceptable anyway.