使用此代码,您可能会遇到麻烦。如果您需要区分不同的类型特征,则必须在编译时完成,而不是在运行时完成。根据您正在执行的操作,您的两个分支之一if
可能无法编译。所以最好转发到一个专门的函数:
void operation_impl(boost::true_type /*other params*/) {
// Treat it is primitive
}
void operation_impl(boost::false_type /*other params*/) {
// Treat it otherwise
}
template<class T>
void operation(/* params*/) {
operation_impl(boost::is_fundamental<T>::type() /*other params*/);
}
使用这种实现技术,只需要编译使用的分支(即正确)。
编辑:
以下是一些附加信息。这个问题的解决方案与模板的实例化有关。我从 切换is_fundamental
到is_array
以显示操作如何失败。
让我们从第一个例子开始:
template <class T>
void fun(T t) {
if(boost::is_array<T>::value)
{
std::cout << "true" << std::endl;
}
else
{
std::cout << "false" << std::endl;
}
}
void f(int i) {
fun(i);
}
它将编译并运行,编译器将看到 if 语句的一个分支将被使用,并将另一个分支作为未使用的代码删除。
在我的第二个示例中,我将在使用数组操作的情况下做一些事情:
template<class T>
void fun(T& t) {
if(boost::is_array<T>::value)
{
std::cout << t[0];
}
else
{
std::cout << t;
}
}
void f(int i) {
fun(i);
}
现在它不会编译。原因是 int 作为模板参数t[0]
格式不正确。您不能在编译时使用此运行时语句来区分代码中需要的类型属性(在本例中是数组的属性和 的使用t[0]
)。
在第三个示例中,我们将通过函数重载来区分编译时间:
template<class T>
void fun_impl(boost::true_type, T& t) {
std::cout << t[0];
}
template<class T>
void fun_impl(boost::false_type, T& t) {
std::cout << t;
}
template<class T>
void fun(T& t) {
fun_impl(typename boost::is_array<T>::type(),t);
}
void f(int i) {
fun(i);
}
这里is_array<T>::type
是true_type
或false_type
。这个结果被用作fun_impl
在编译时选择正确的重载的选择器,并且只有选择的重载被实例化和编译。
通常,此类技术用于在编译时选择最佳实现,该实现可能仅在类型具有某些属性时才可编译。
第二次编辑:
static if
如果是语言的一部分,这当然会改变。