3

In certain cases, implicit type conversion may not be desired.

For example:

#include <string>

using namespace std;

void f(bool)
{}

void f(string)
{}

int main()
{
    auto p = "hello";
    f(p); // Oops!!! Call void f(bool); rather than void f(string);
}

If the C++ standard supports the keyword explicit can be used to qualify function parameters, the code may be changed as follows:

#include <string>

using namespace std;

void f(explicit bool) // Illegal in current C++11 standard!
{}

void f(string)
{}

int main()
{
    auto p = "hello";
    f(p); // Call void f(string);

    bool b = true;
    f(b); // Call void f(bool);

    f(8); // Error!
}

Why does the C++ standard not support such a handy feature?

xmllmx
  • 39,765
  • 26
  • 162
  • 323
  • I don't follow. `const char*` is a better match to `bool` than `std::string`. The former is a trivial construction, the latter isn't. So the problem you're trying to fix is..? – WhozCraig Mar 02 '14 at 04:52
  • In this case, I don't want to implicitly convert `const char*` to `bool`, how to do? In other words, how to disable implicit type conversion when passing arguments if I want to? – xmllmx Mar 02 '14 at 04:54
  • So you don't want implicit conversion to bool, but you *do* want it implicitly convert it to `std::string`? Is that the crux ? – WhozCraig Mar 02 '14 at 04:55
  • Yes, I just want to disable one case and preserve other cases. How to do? – xmllmx Mar 02 '14 at 04:56
  • In this case you can solve your problem with literally three lines of code by defining an overload that takes `const char*` and then calling `f(string)`. Could you come up with an example where this proposed use of the `explicit` keyword would save you more than three lines of typing? – Brian Bi Mar 02 '14 at 05:01
  • @BrianBi, I think `void f(explicit bool)` is rather elegant to express what I mean. Why should I do anymore? – xmllmx Mar 02 '14 at 05:12
  • 2
    @xmllmx If people had this problem often enough, and existing workarounds were unsatisfactory enough, then it might have a reasonable chance of being voted into the standard. But I think that neither is the case, and "elegance" is not a good reason to add more features to a language whose standard already has over 1300 pages. – Brian Bi Mar 02 '14 at 05:21
  • 5
    IMO, wanting this is a pretty good sign that you're using function overloading inappropriately. What does `f` do that it makes sense for it to take either `bool` or `string` as its parameter, and carry out logically equivalent processing either way? – Jerry Coffin Mar 02 '14 at 05:24

1 Answers1

4
#include <string>
#include <type_traits>      // std::is_same
#include <utility>          // std::enable_if
using namespace std;

template< class Value >
struct Explicit_
{
    Value    value;

    operator Value() const { return value; }

    template<
        class Arg,
        class Enabled = typename enable_if< is_same< Arg, Value >::value, void >::type
        >
    Explicit_( Arg const v ): value( v ) {}
};

void f( Explicit_<bool> ) // Valid in current C++11 standard!
{}

void f( string )
{}

int main()
{
    auto p = "hello";
    f(p); // Call void f(string);

    bool b = true;
    f(b); // Call void f(bool);

    f(8); // Error!
}
Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • I have known this technique, but I think this technique has a disadvantage: Consider Explicit_, If the class T has heavy copy cost, then double copy will occur. Moreover, I think `void f(explicit bool)` is more expressive, and it should be direct supported by the standard. – xmllmx Mar 02 '14 at 05:06
  • 1
    @xmllmx: if concern over copy costs, then simply avoid copying. ;-) That is, wrap a reference instead of a value. – Cheers and hth. - Alf Mar 02 '14 at 05:09