Can you use keyword explicit to prevent automatic conversion of method parameters?

I know you can use C++ keyword 'explicit' for constructors of classes to prevent an automatic conversion of type. Can you use this same command to prevent the conversion of parameters for a class method?

I have two class members, one which takes a bool as a param, the other an unsigned int. When I called the function with an int, the compiler converted the param to a bool and called the wrong method. I know eventually I'll replace the bool, but for now don't want to break the other routines as this new routine is developed.

No, you can't use explicit, but you can use a templated function to catch the incorrect parameter types.

With C++11, you can declare the templated function as deleted. Here is a simple example:

#include <iostream>

struct Thing {
    void Foo(int value) {
        std::cout << "Foo: value" << std::endl;
    }

    template <typename T>
    void Foo(T value) = delete;
};

This gives the following error message if you try to call Thing::Foo with a size_t parameter:

error: use of deleted function
    ‘void Thing::Foo(T) [with T = long unsigned int]’

In pre-C++11 code, it can be accomplished using an undefined private function instead.

class ClassThatOnlyTakesBoolsAndUIntsAsArguments
{
public:
  // Assume definitions for these exist elsewhere
  void Method(bool arg1);
  void Method(unsigned int arg1);

  // Below just an example showing how to do the same thing with more arguments
  void MethodWithMoreParms(bool arg1, SomeType& arg2);
  void MethodWithMoreParms(unsigned int arg1, SomeType& arg2);

private:
  // You can leave these undefined
  template<typename T>
  void Method(T arg1);

  // Below just an example showing how to do the same thing with more arguments
  template<typename T>
  void MethodWithMoreParms(T arg1, SomeType& arg2);
};

The disadvantage is that the code and the error message are less clear in this case, so the C++11 option should be selected whenever available.

Repeat this pattern for every method that takes the bool or unsigned int. Do not provide an implementation for the templatized version of the method.

This will force the user to always explicitly call the bool or unsigned int version.

Any attempt to call Method with a type other than bool or unsigned int will fail to compile because the member is private, subject to the standard exceptions to visibility rules, of course (friend, internal calls, etc.). If something that does have access calls the private method, you will get a linker error.

C++: "explicit" should be used on single-parameter constructors and , Such a constructor defines an implicit conversion from the type or types of its In this recipe, we will see how to use explicit constructors and conversion operators. they are functions or function templates), use the explicit specifier in the declaration. Similarly, f7 , f8 , and f9 invoke the constructor with two parameters​. No, you can't use explicit, but you can use a templated function to catch the incorrect parameter types. With C++11 , you can declare the templated function as delete d. Here is a simple example:

No. explicit prevents automatic conversion between specific classes, irrespective of context. And of course you can't do it for built-in classes.

Using explicit constructors and conversion operators to avoid implicit , In C++, any constructor that takes a single argument acts as a blueprint for create a Stonewt object myCat = 19.6; // use Stonewt(double) to convert 19.6 to Only a constructor that can be used with just one argument works as a conversion function. So C++ added a new keyword, explicit, to turn off the automatic aspect. In Ruby 2, you can write a delegation method by accepting a *rest argument and a &block argument, and passing the two to the target method. In this behavior, the keyword arguments are also implicitly handled by the automatic conversion between positional and keyword arguments. def foo (* args, & block) target (* args, & block) end Ruby 3

The following is a very basic wrapper that can be used to create a strong typedef:

template <typename V, class D> 
class StrongType
{
public:
  inline explicit StrongType(V const &v)
  : m_v(v)
  {}

  inline operator V () const
  {
    return m_v;
  }

private:
  V m_v; // use V as "inner" type
};

class Tag1;
typedef StrongType<int, Tag1> Tag1Type;


void b1 (Tag1Type);

void b2 (int i)
{
  b1 (Tag1Type (i));
  b1 (i);                // Error
}

One nice feature of this approach, is that you can also distinguish between different parameters with the same type. For example you could have the following:

class WidthTag;
typedef StrongType<int, WidthTag> Width;  
class HeightTag;
typedef StrongType<int, HeightTag> Height;  

void foo (Width width, Height height);

It will be clear to the clients of 'foo' which argument is which.

C++ Primer Plus: C++ Primer Plus _p6, A call to function Foo as - Foo(4); - would implicitly convert integer 4 argument constructor behaves as an implicit conversion function. Keyword explicit tells compiler to not use the constructor for implicit conversion. For example declaring Bar's constructor explicit as - explicit Bar(int i); - would prevent us  In summary, if your single-parameter constructor converts the parameter into an object of your class, you probably don't want to use the explicit keyword. But if you have a constructor that simply happens to take a single parameter, you should declare it as explicit to prevent the compiler from surprising you with unexpected conversions.

Something that might work for you is to use templates. The following shows the template function foo<>() being specialized for bool, unsigned int, and int. The main() function shows how the calls get resolved. Note that the calls that use a constant int that don't specify a type suffix will resolve to foo<int>(), so you'll get an error calling foo( 1) if you don't specialize on int. If this is the case, callers using a literal integer constant will have to use the "U" suffix to get the call to resolve (this might be the behavior you want).

Otherwise you'll have to specialize on int and use the "U" suffix or cast it to an unsigned int before passing it on to the unsigned int version (or maybe do an assert that the value isn't negative, if that's what you want).

#include <stdio.h>

template <typename T>
void foo( T);

template <>
void foo<bool>( bool x)
{
    printf( "foo( bool)\n");
}


template <>
void foo<unsigned int>( unsigned int x)
{
    printf( "foo( unsigned int)\n");
}


template <>
void foo<int>( int x)
{
    printf( "foo( int)\n");
}



int main () 
{
    foo( true);
    foo( false);
    foo( static_cast<unsigned int>( 0));
    foo( 0U);
    foo( 1U);
    foo( 2U);
    foo( 0);
    foo( 1);
    foo( 2);
}

C++, has two arguments, so it cannot be used to convert types. Having a constructor work as an automatic typeconversion function seems like a nice So recent C++ implementations have a new keyword, explicit, to turn off the automatic aspect. That is, you can declare the constructor this way: explicit Stonewt(double lbs); // no  As discussed in this GFact, in C++, if a class has a constructor which can be called with a single argument, then this constructor becomes conversion constructor because such a constructor allows conversion of the single argument to the class being constructed.

The currently accepted answer (using a private templated function) is nice, but outdated. With C++11, we can use deleted functions instead:

#include <iostream>

struct Thing {
    void Foo(int value) {
        std::cout << "Foo: value" << std::endl;
    }

    template <typename T>
    void Foo(T value) = delete;
};

int main() {
    Thing t;
    int int_value = 1;
    size_t size_t_value = 2;

    t.Foo(int_value);

    // t.Foo(size_t_value);  // fails with below error
    // error: use of deleted function
    //   ‘void Thing::Foo(T) [with T = long unsigned int]’

    return 0;
}

This conveys the intent of the source code more directly and supplies the user with a clearer error message when trying to use the function with disallowed parameter types.

C++ Primer Plus, Portable Documents, A method to compare two Complex numbers with a single argument, then this constructor becomes conversion constructor We can avoid such implicit conversions as these may lead to unexpected results. For example, if we try the following program that uses explicit keyword with constructor, we get compilation error. Such conversions can be useful in some cases, but more often they can lead to subtle but serious errors in your code. As a general rule, you should use the explicit keyword on a constructor (and user-defined operators) to prevent this kind of implicit type conversion:

Use of explicit keyword in C++, A default constructor is a constructor which can be called with no arguments (​either defined with an empty parameter list, or with default  An explicit conversion exists (are you missing a cast?) So, if we want to assign a value of larger data type to a smaller data type we perform explicit type casting. This is useful for incompatible data types where automatic conversion cannot be done.

Default constructors, Predef defines two conversions from String : one to WrappedString and another that can be passed “automatically”, so to speak, or a conversion from one type to One can pass these parameters explicitly, which is how one uses breakOut , for The method getIndex can receive any object, as long as there is an implicit​  For an explicit reference conversion to succeed at run-time, the value of the source operand must be null, or the actual type of the object referenced by the source operand must be a type that can be converted to the destination type by an implicit reference conversion (Implicit reference conversions) or boxing conversion (Boxing conversions).

Where does Scala look for implicits? | FAQ, How do I explicitly select which version of a function template should get called? What is a Can you provide an example of template specialization that doesn't use foo and bar ? But most of the How can I avoid linker errors with my template functions? How does the C++ keyword export help with template linker errors? Conversions with helper classes: To convert between non-compatible types, such as integers and System.DateTime objects, or hexadecimal strings and byte arrays, you can use the System.BitConverter class, the System.Convert class, and the Parse methods of the built-in numeric types, such as Int32.Parse.

Comments
  • Wondered this same thing and think this would be useful syntax for certain free functions. Normally I want the reference to a derived class to implicitly yield the base class, except in the cases where undesirable slicing could happen, such as with a swap() function. Having swap(explicit Foo& lhs, explicit Foo& rhs) would be comforting.
  • But this will disable ALL automatic conversions.
  • Yes, it will disable ALL automatic conversions. Dan wants to "prevent the conversion of parameters for a class method", per the question text, and this method satisfies that. There are ways using template specialization that we could 'map' basic types to specific methods if so desired.
  • I realize this is an old answer. Is there a way to use delete or some other modern C++ features to accomplish the same thing without this private hackiness? Edit: Ahah! It works!
  • Yes, you can use delete, although I wouldn't call the use of private hacky. Just, not the latest way. This is one place StackOverflow doesn't always do well, dealing with change. How would you feel about incorporating your answer into mine, @Apollys, with sections for C++11 and pre-C++11?
  • Done. I placed the C++11 solution first because it really should be the go-to option these days.
  • Voted up; this does answer the question correctly, after all.
  • Although the question is rather old ( 9 years thought ) : Every time I want to call foo with two Integer parameters I have to write foo( Height ( int_1 ), Width ( int_2 ) ) which will find the explicit conversion operator through Argument Dependent Lookup / Koenig's Lookup ?
  • @SebTu: No. Height and Width must be found by non ADL lookup. The expression Height(int_1) is an explicit type cast that results in the constructor of Height being called. ADL does not apply here. Therefore, to refer to NS::Height or NS::Width then we must either use a using directive/declaration or explicitly qualify the names.
  • I thought about doing it this way, too; having foo<int> call foo<unsigned int> to explicitly map. This is a better way if he wants to allow some conversions but not all.
  • Actually, this is really the same method as yours. When I quickly scanned yours shortly before posting I got thrown off by the multi-parameter prototypes and thought your technique was doing something different that I didn't fully understand. I should have read more closely.