无论y
,x
是x
还是y
,我都试图创建一个将int
分配给std::string
的函数。我写了这段代码:
#include <iostream>
#include <string>
#include <typeinfo>
template <typename T>
T& assign(T& x, T& y){
if ( typeid(x).name() == "Ss" && typeid(y).name() == "Ss" ){
std::string k = static_cast<std::string>(y);
x = k;
return x;
}
else if ( typeid(x).name() == "i" && typeid(y).name() == "i" ){
int k = static_cast<int>(y);
x = k;
return x;
}
else{
std::cout << "uncorrect assignment" << std::endl;
}
}
int main(){
std::string a = "empty_string";
std::string b = "Hi there";
assign(a, b);
std::cout << a << std::endl;
}
但它不起作用。 它给出了错误:
[Error] invalid static_cast from type ‘std::basic_string<char>’ to type
第14行:
int k = static_cast<int>(y);
我无法理解,问题是什么?
我知道反对意见:我可能刚刚将函数赋值定义为:
template <typename T>
T& assign(T& x, T& y){
x = y;
}
哪个有效。但是,我正在研究另一个更复杂的功能,我必须(或者至少我没有找到任何方法)使用static_cast
。
所以,如果可以的话,请向我解释这个例子中的错误是什么,我可能会尝试修复我正在处理的功能。
非常感谢, 西蒙。
答案 0 :(得分:2)
要做你想做的事,你需要C ++ 17和if constexpr
。使用编译时工作的东西,而不是运行时的typeid
。
问题在于,使用您的代码typeid
允许,运行时,选择代码的if或else部分,但编译器必须编译这两部分。所以必须编译
int k = static_cast<int>(y);
x = k;
当T
为std::string
时。这给出了错误。
你需要一个类型特征(例如std::is_same
),它被评估为编译时,以及一个避免编译错误部分的构造。这个构造是if constexpr ( <test> )
(其中<test>
是有价值的编译时间),但不幸的是,它只能从C ++ 17中获得。
所以,在C ++ 17中你可以编写
template <typename T>
void assign (T & x, T const & y)
{
if constexpr ( std::is_same<T, std::string>::value ) {
std::string k = static_cast<std::string>(y);
x = k;
}
else if constexpr ( std::is_same<T, int>::value ) {
int k = static_cast<int>(y);
x = k;
}
else {
std::cout << "uncorrect assignment" << std::endl;
}
}
但是,在C ++ 17之前,你必须遵循不同的方式。
答案 1 :(得分:0)
要在函数内单独处理不同的类型,可以选择将重载function call operators的本地struct
定义为不同的类型:
#include <iostream>
#include <string>
template<typename T>
T& assign(T& x, const T& y) {
struct {
void operator()(std::string& lhs, const std::string& rhs) {
std::cout << "Type is std::string." << std::endl;
lhs = rhs;
}
void operator()(int& lhs, const int& rhs) {
std::cout << "Type is int." << std::endl;
lhs = rhs;
}
} assign_impl;
assign_impl(x, y);
return x;
}
int main() {
/* Test No. 1 */ {
std::string dest, src = "Foo";
std::cout << "Test result: " << assign(dest, src) << std::endl;
}
/* Test No. 2 */ {
int dest, src = 32;
std::cout << "Test result: " << assign(dest, src) << std::endl;
}
}
上面的代码适用于C ++ 98及更高版本,但它的缺点是,如果你尝试将它与未处理的类型一起使用,它会引发编译器错误。