2014-12-21 5 views
8

Было бы полезно иметь параметры «constexpr», чтобы отличать известные от компилятора значения и, следовательно, иметь возможность обнаруживать ошибки во время компиляции. Примеры:Почему параметры 'constexpr' не допускаются?

int do_something(constexpr int x) 
{ 
    static_assert(x > 0, "x must be > 0"); 
    return x + 5; 
} 

int do_something(int x) 
{ 
    if(x > 0) { cout << "x must be > 0" << endl; exit(-1); } 
    return x + 5; 
} 

int var; 

do_something(9); //instance 'do_something(constexpr int x)' and check arg validity at compile-time 

do_something(0); //produces compiler-error 

do_something(var); //instance 'do_something(int x)' 

Это недопустимый код. Может ли кто-нибудь объяснить мне, почему это невозможно реализовать?

EDIT:

Использование шаблонов пользователи должны гарантировать, что литералы всегда передаются в качестве аргументов шаблона, а не как функции те, которые очень неудобно:

template<int x> 
int do_something() 
{ 
    static_assert(x > 0, "x must be > 0"); 
    return x + 5; 
} 

int do_something(int x) 
{ 
    if(x > 0) { cout << "x must be > 0" << endl; exit(-1); } 
    return x + 5; 
} 

int var; 

do_something(9); //instance 'do_something(int x)' and doesn't checks validity at compile-time 

do_something(0); //same as above, if check was performed - compiler error should occur 

do_something<9>(); //instance template 'do_something<int>()' 

do_something<0>(); //produces compiler error 

do_something(var); //instance 'do_something(int x)' 
+1

Не можете ли вы сделать это с помощью шаблона? Более конкретно, с параметрами шаблона без типа? – Borgleader

+0

Тогда пользователь моей функции должен предоставлять разные синтаксисы для вызова в зависимости от того, известен ли параметр во время компиляции. – AnArrayOfFunctions

+0

Предполагается, что утверждение() может быть оптимизировано в случае, когда передано значение constexpr. –

ответ

-4

Хотя это звучит замечательно в теории, это не значит, что полезный в реальном мире. Большинство аргументов функций не являются константами времени компиляции, и многие ограничения не точно известны во время компиляции.

Чтобы указать и реализовать такую ​​перегрузку, будет значительная работа, и она не будет использоваться так сильно. Когда у вас есть время и параметры компиляции, вы можете обычно оценивать всю функцию во время компиляции, а это означает, что перегрузка не требуется.

+1

Это не отвечает конкретно WHY, что и задается вопросом. – cybermonkey

+0

@cybermonkey Я, очевидно, не согласен. Я попытался объяснить, почему эта функция не соответствует стандарту, описывая, почему она недостаточно полезна для оправдания усилий.В отличие от другого ответа на этот вопрос, который не отвечает на то, почему каким-либо образом формируется или формируется, а просто пытается описать обходной путь (т. Е. Ставит фактический код, который просто показывает, что я пишу в своем втором абзаце). –

2

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

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

Я считаю, что это будет делать то, что вы хотите:

constexpr int do_something(int x) 
{ 
    if(x <= 0) 
    { 
     std::cout << "x must be > 0" << std::endl; exit(-1); 
    } 
    return x + 5; 
} 

constexpr int compiletime_good = do_something(5); 
constexpr int compiletime_bad = do_something(0); // Fails at compile-time 

int runtime_good = do_something(5); 
int runtime_bad = do_something(0); // Fails at runtime 

constexpr int val_good = 5; 
constexpr int val_bad = 0; 

do_something(val_good); 
do_something(val_bad); // Fails at run-time 

int valrun_good = 5; 
int valrun_bad = 0; 

do_something(valrun_good); 
do_something(valrun_bad); // Fails at run-time 

Хитрость здесь потерпеть неудачу во время компиляции таким образом, что не требует static_assert, а также не будет во время выполнения.

+1

Что потребует, чтобы каждый экземпляр do_something вызывался там, где ожидается «constexpr», что не лучше, чем использование шаблонов. – AnArrayOfFunctions

+0

@FISOCPP Ярмарка достаточно. Я предполагаю, что у нас нет явного способа включить параметры constexpr в то, как вы спрашиваете, так это то, что никто не столкнулся с трудностями, чтобы написать и получить предложение. Я бы хотел, чтобы это произошло, но это звучит как большая работа. –

+1

Нужно, конечно, использовать существующее средство для сообщения об ошибке утверждения, а не посыпать вызовы 'std :: exit()' на всей кодовой базе. В противном случае это очень хорошо. –