class BaseClass{
public:
std::string name;
BaseClass(std::string typeName) : name(typeName) {};
std::string GetType(){ return name; }
};
template<typename T>
class DerivedClass : public BaseClass{
public:
T val;
DerivedClass(std::string typeName, T arg) : BaseClass(typeName), val(arg) {};
};
template<typename U, typename L>
void foo1(U & arg1, L & arg2)
{
std::cout << arg1.val + arg2.val << std::endl;
}
void foo(BaseClass *arg1, BaseClass *arg2)
{
if(arg1->GetType() == "Int")
{
auto p1 = (DerivedClass<int>*)arg1;
if(arg2->GetType() == "Int")
{
auto p2 = (DerivedClass<int>*)arg2;
foo1(*p1, *p2);
}
else if(arg2->GetType() == "Float")
{
auto p2 = (DerivedClass<float>*)arg2;
foo1(*p1, *p2);
}
//else if () AND SO ON ........
}
else if(arg1->GetType() == "Float")
{
auto p1 = (DerivedClass<float>*)arg1;
if(arg2->GetType() == "Int")
{
auto p2 = (DerivedClass<int>*)arg2;
foo1(*p1, *p2);
}
else if(arg2->GetType() == "Float")
{
auto p2 = (DerivedClass<float>*)arg2;
foo1(*p1, *p2);
}
}
//else if () AND SO ON .....
}
int main()
{
BaseClass *k1 = new DerivedClass<int>("Int", 2);
BaseClass *k2 = new DerivedClass<float>("Float", 4.32);
foo(k1, k2);
return 0;
}
我有一些与上面的测试用例类似的问题。 在函数 foo 中,是否有更优雅的方法将多种类型解析为 ifs 的梯子来运行模板函数? 对于 1 或 2 个参数来说,if 的阶梯并没有那么糟糕,但它会变成 (参数计数)^(类型计数);
最佳答案
您可以使用一些模板魔法来为您生成if
...else
链。首先,编写一个通用的编译时迭代函数:
template <typename TF, typename... Ts>
void for_each_arg(TF&& f, Ts&&... xs)
{
return (void)(int[]){(f(std::forward<Ts>(xs)), 0)...};
}
您还需要将类型绑定(bind)到字符串的东西:
template <typename T>
struct bound_type
{
using type = T;
std::string _name;
bound_type(std::string name) : _name{std::move(name)} { }
};
然后您可以使用它来检查您感兴趣的类型:
void foo(BaseClass *arg1, BaseClass *arg2)
{
const auto for_bound_types = [](auto&& f)
{
return for_each_arg(std::forward<decltype(f)>(f),
bound_type<int>{"Int"},
bound_type<float>{"Float"},
bound_type<double>{"Double"});
};
for_bound_types([&](const auto& t1)
{
if(arg1->GetType() != t1._name) return;
for_bound_types([&](const auto& t2)
{
if(arg2->GetType() != t2._name) return;
using t1_type = typename std::decay_t<decltype(t1)>::type;
using t2_type = typename std::decay_t<decltype(t2)>::type;
auto& p1 = static_cast<DerivedClass<t1_type>&>(*arg1);
auto& p2 = static_cast<DerivedClass<t2_type>&>(*arg2);
foo1(p1, p2);
});
});
}
我想避免在这里使用std::string
,但是编译时字符串在C++中非常困难。类似于 typestring可以用它来代替。
在 C++17 中,由于折叠表达式,for_each_arg
将是多余的。 std::apply
也可用于实现 for_bound_types
。
const auto for_bound_types = [](auto&& f)
{
return std::apply([&](auto... xs){ (f(xs), ...); },
std::make_tuple(bound_type<int>{"Int"},
bound_type<float>{"Float"},
bound_type<double>{"Double"}));
};
关于C++ 模板在模板函数实例化时类型未知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42809955/