使用这段代码可能会遇到问题。如果您需要区分不同的类型特征,则必须在编译时而不是运行时进行。根据您执行的操作,您的if
语句中的两个分支中的一个可能无法编译。因此,最好转发到专门的函数:
void operation_impl(boost::true_type ) {
}
void operation_impl(boost::false_type ) {
}
template<class T>
void operation() {
operation_impl(boost::is_fundamental<T>::type() );
}
使用这种实现技术,只需要编译使用的分支(即正确的分支)。
编辑:
以下是一些额外的信息。解决此问题与模板的实例化有关。我从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
,那么这个情况当然会发生改变。