2016-12-20 1 views
4

У меня есть следующий код:предотвратить отливку междунар при вызове функции

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

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

Когда я пытаюсь скомпилировать это, он дает ошибку, которая не может конвертировать int32_t* в int64_t*, который является то, что я хочу.

Возможно ли получить некоторые подобные ошибки при попытке вызвать foo(a)?

+4

[Это] (HTTP://coliru.stacked-crooked.com/a/8e3defa4902f44ad)? – LogicStuff

+1

Зачем вам такая ошибка? Как уже упоминалось, это преобразование всегда безопасно. Если вы конвертировали 'int64_t' в' int32_t', вы могли получить ошибку, используя не сужающееся преобразование: 'foo ({a})' – alexeykuzmin0

+0

Чтобы развернуть комментарий @ alexeykuzmin0, что такое * актуальная * проблема что вы пытаетесь решить? [Связанное чтение о проблеме XY] (http://xyproblem.info/). –

ответ

7

В качестве временного решения можно перегрузить Foo с удаленной версии:

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

В качестве более общего решения вы можете создать удаленный шаблон функции, а затем специализироваться его int64_t (благодаря @Someprogrammerdude):

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

template<> 
void foo(int64_t x) {} 

Процент не компилируется с clang 3.8, но компилируется с clang 3.9 и gcc 6.2.

+0

Теперь * это * умный способ. Отлично сработано. – Bathsheba

+5

И если OP хочет запретить * anything *, но функцию аргумента 'int64_t', можно использовать шаблоны и специализацию шаблонов. –

+0

Он по-прежнему принимает 'int' или что-то еще. Вы должны удалить все возможные перегрузки. Я ошибаюсь? – skypjack

1

Если изменить подпись

void foo(int64_t& x)

тогда, потому что int32_t не может связывать к не- const ссылкой на int64_t, компиляция потерпит неудачу.

Но эта техника страдает от того, что теперь fooможет изменить переменную, переданную ему через ссылку. Естественно, вы могли бы контролировать это в foo, но в целом мне это не кажется хорошей идеей.

Обратите также внимание на то, что он не может связываться с анонимным временным кодом даже для правильного типа, например. foo((int64_t)1);

+0

@ M.M Я ущипнул это. Единственное доверие, которое, как мне кажется, имеет этот ответ, это то, что он работает для pre C++ 11. – Bathsheba

3

Вы можете использовать шаблон и static_assert:

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

Или полной специализации, где основной шаблон не определен или удален:

template<typename> 
void foo(T); 

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

template<> 
void foo(int64_t x) { 
    // ... 
} 
Смежные вопросы