C ++: cannot initialize parameter of type char * 'with lvalue of type' double 'in template function using conditional conditional expression
I want to write a template function to copy data from one array to another array. I want to handle arrays int
, double
and char*
(string) in my program.
template<typename T>
void copy_key(T *destination, int destination_index, T *source, int source_index){
if (typeid(T) == typeid(int) or typeid(T) == typeid(double)){
destination[destination_index] = source[source_index];
} else {
// char* case
strcpy(destination[destination_index], source[source_index]);
}
}
If I call copy_key()
like below, I get the error: Cannot initialize parameter of type char * 'with lvalue of type' double '.
int main(int argc, const char * argv[]) {
double from_array[3] = {1.0,2.0,3.0};
double to_array[3];
copy_key(to_array, 0, from_array, 2);
std::cout << to_array[0] << std::endl;
return 0;
}
I thought that if there T
was double
, the else block would not be injected. My question is, how do I properly use the condition for the template type in my example?
source to share
I thought that if there
T
wasdouble
, the else block would not be injected.
You thought right. But your assumption about its consequences is incorrect.
Just because some code won't get executed doesn't mean that it, along with the rest of the program, shouldn't be well formed.
Even if in this case the compiler can prove that the line will not be executed, such a proof is practically impossible for all possible programs in general, so it cannot affect the correctness of the program.
A typical solution is to use either overloads or specialized templates:
void copy_key(char *destination, int destination_index, const char *source, int source_index){
strcpy(...);
}
void copy_key(double *destination, int destination_index, double *source, int source_index){
destination[destination_index] ...
}
The upcoming C ++ 17 will be constexpr if
one that allows you to conditionally compile blocks within a single function.
source to share
In C ++ 17, you will if constexpr
end up evaluating only one branch of the if statement.
At the moment, both the if-part and else-part must be valid for the type T
. If you want it to be different for different types, you will have to specialize the template.
source to share
In C ++ 14 and earlier, use template specialization instead of conventions.
C ++ is a compiled language, not interpretable. When a templated function is compiled for a specific specific use, the entire function needs to be compiled, not just the branches that need to be executed. The compiler generally cannot figure out the exact path that your code will accept for all inputs a priori.
template<typename T>
void copy_key(T *destination, int destination_index, T *source, int source_index){
destination[destination_index] = source[source_index];
}
template<>
void copy_key(const char** destination, int destination_index, const char** source, int source_index) {
// char* case
strcpy(destination[destination_index], source[source_index]);
}
source to share
No, you can not. Set as:
template<typename T>
void copy_key(T *destination, int destination_index, T *source, int source_index){
if (some_condition){ // some_condition met
destination[destination_index] = source[source_index];
} else { // some condition not met
// char* case
strcpy(destination[destination_index], source[source_index]);
}
}
easier to see.
Instead, you need "conditional compilation" (template specialization)
source to share