bbvan
bbvan

Reputation: 658

prevent casting of int when calling function

I have the following code:

void foo(int64_t x) {}
void bar(int64_t* x) {}

int main() {
    int32_t a = 3;
    foo(a);
    bar(&a);
}

When I try to compile this, it gives an error that cannot convert int32_t* to int64_t*, which is what I want.

Is it possible to get some similar errors when I try to invoke foo(a) ?

Upvotes: 4

Views: 290

Answers (3)

Edgar Rokjān
Edgar Rokjān

Reputation: 17483

As a workaround you can overload foo with the deleted version:

void foo(int32_t x) = delete;
void foo(int64_t x) {}

As a more general solution you may create a deleted function template and then specialize it for int64_t (thanks to @Someprogrammerdude):

template<typename T>
void foo(T) = delete;

template<>
void foo(int64_t x) {}

Interestingly, it doesn't compile with clang 3.8, but compiles fine with clang 3.9 and gcc 6.2.

Upvotes: 8

Bathsheba
Bathsheba

Reputation: 234715

If you change the signature to

void foo(int64_t& x)

then, because an int32_t cannot bind to a non-const reference to an int64_t, compilation will fail.

But this technique suffers from the fact that now foo could modify a variable passed to it through the reference. Naturally you could control that in foo itself, but on the whole it doesn't seem like a good idea to me.

Note also that it can't bind to an anonymous temporary of even the correct type, e.g. foo((int64_t)1);

Upvotes: 1

skypjack
skypjack

Reputation: 50550

You can use a template and a static_assert:

template<typename T>
void foo(T x) {
    static_assert(std::is_same<int64_t, T>::value, "!");
    // ...
}

Or a full specialization, where the primary template isn't defined or is deleted:

template<typename>
void foo(T);

// This should be fine as well
//
// template<typename>
// void foo(T) = delete;

template<>
void foo(int64_t x) {
    // ...
}

Upvotes: 3

Related Questions