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?

+3


source to share


4 answers


I thought that if there T

was double

, 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.

+5


source


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.

+3


source


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]);
}

      

+3


source


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)

+1


source







All Articles