1

I just tried to use explicit operator bool() for the first time and its behavior is quite unexpected to me. Can someone please shed some light on why the following sections marked with // does not work.

The convertible class would e.g. be a smart pointer class with the ability to check for the validity of the contained data.

struct convertible
{
  explicit operator bool() const
  {
    return ptr;
  }

  void* ptr = nullptr;
};

bool testReturn()
{
  convertible test;
  // does not work
  return test;
}

bool testReturn2()
{
  convertible test;
  // does not work
  return test == true;
}

bool testReturn3()
{
  convertible test;
  // works ?!
  return !test;
}

int main()
{
  convertible test;
  // works
  if (test) { }
  // works
  bool init(test);
  bool tested = test;
  bool tested2 = testReturn();
  bool tested3 = testReturn2();
  bool tested4 = testReturn3();
  return 0;
}

With GCC I get:

milian@minime:/tmp$ g++ --version
g++ (GCC) 4.8.2 20131219 (prerelease)
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

milian@minime:/tmp$ g++ -std=c++11 test.cpp 
test.cpp: In function ‘bool testReturn()’:
test.cpp:15:10: error: cannot convert ‘convertible’ to ‘bool’ in return
  return test;
          ^
test.cpp: In function ‘bool testReturn2()’:
test.cpp:22:15: error: no match for ‘operator==’ (operand types are ‘convertible’ and ‘bool’)
  return test == true;
              ^
test.cpp:22:15: note: candidate is:
test.cpp:22:15: note: operator==(int, int) <built-in>
test.cpp:22:15: note:   no known conversion for argument 1 from ‘convertible’ to ‘int’
test.cpp: In function ‘int main()’:
test.cpp:39:17: error: cannot convert ‘convertible’ to ‘bool’ in initialization
  bool tested = test;

With Clang it's similar:

milian@minime:/tmp$ clang++ --version
clang version 3.4 (tags/RELEASE_34/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
milian@minime:/tmp$ clang++ -std=c++11 test.cpp 
test.cpp:15:10: error: no viable conversion from 'convertible' to 'bool'
  return test;
        ^~~~
test.cpp:22:15: error: invalid operands to binary expression ('convertible' and 'int')
  return test == true;
        ~~~~ ^  ~~~~
test.cpp:39:8: error: no viable conversion from 'convertible' to 'bool'
  bool tested = test;
      ^        ~~~~
3 errors generated.

2 Answers 2

3

If your goal is to disable certain conversions, just disable them through the delete specifier:

struct convertible
{
    operator bool() const //(Implicit) Conversion to bool allowed
    {
        return true;
    }

    operator int() const = delete; //Implicit/Explicit conversions to int disallowed 
                                   //(Results in compilation error).
};


int main()
{
    convertible c;

    if( c )
        ...

    int a = c; //ERROR
    int b = (int)c; //ERROR (The same for static_cast<int>(c) )
}

You could also delete all types except which are explicitly overloaded using a templated version of the conversion operator:

struct foo
{
    operator bool() const //Explicit overload for bool
    {
       return true; 
    }

  template<typename T>
  operator T() const = delete; //Everithing which is not a bool (Everithing which  
                               //does not fit in the explicit overload) would  
                               //resolve to this operator and will fail.
};


int main()
{
    foo f;

    bool b = f; //OK
    int i = f;  //ERROR
    char c = f; //ERROR
    etc...
}
Sign up to request clarification or add additional context in comments.

3 Comments

Awesome - that's just what I want! What's odd though is that this still doesn't work as expected: foo f; f == true; It apparently tries to convert with an int here?
@milianw First: Don't write conitionals like if( f == true ). Just write if( f ). == true is redundant. BTW true and false keywords are defined as integers? LOL. Just don't write == true
@milianw I have posted a question about the topic. Seems like boolean comparisons are promoted to integral comparisons, so in the case of a user defined conversion vs bool comparison the integer conversion is requested.
0

If your cast operator is explicit, you need to cast it, something like:

return static_cast<bool>(test);

2 Comments

Yes, I know it's explicit. I want to disallow conversions to anything but bool - i.e. the implicit upcasting of bool to int is what I'd expect to see forbidden. Yet a conversion to bool should be just fine, no? Put differently: What's the difference between bool a = convertible; and if (convertible) - both should convert to bool just fine, no?
A bit simpler than static_cast could be bool(test). @milianw: The standard explicitly states that when used as a condition it will use an explicit conversion operator. The aim is to support explicit operator bool() const in things like istream, rather than resorting to the good old safe bool idiom.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.