如何在编译时选择方法

How to select the method at compilation time?

本文关键字:选择 方法 编译      更新时间:2023-10-16

我记得读过一些文章,使用新的C++功能在编译器时实现选择,但不知道该怎么做。例如,我有一个执行以下操作的方法

template<class T>
void foo()
{
   if (std::is_abstract<T>::value)
         do something;
   else
         do others.
}

编译时决策通常通过重载选择来完成。

void foo_impl(std::true_type) {
    do something;
}
void foo_impl(std::false_type) {
    do others.
}
template<class T>
void foo()
{
   foo_impl(std::is_abstract<T>());
}

如果两个分支都编译,上面的代码实际上是可以的,并将在编译时进行选择:编译器将检测到一个分支已死并且永远不会使用。优化时,没有自尊的编译器会使用分支。

特别是当分支可能无法根据类型进行编译时,您可以使用 std::enable_if 有条件地使重载可用:

template <typename T>
typename std::enable_if<std::is_abstract<T>::value>::type foo()
{
    do something
}
template <typename T>
typename std::enable_if<!std::is_abstract<T>::value>::type foo()
{
    do other
}

std::is_abstract 实用程序是类型特征的一个例子,我喜欢遵循经典的选择器习语:

#include<iostream>
#include<type_traits>
template<bool>
struct algorithm_selector {
  static void implementation() {
    std::cout<<"I am using the default implementation"<<std::endl;
  }
};
template<>
struct algorithm_selector<true> {
  static void implementation() {
    std::cout<<"I am using the 'custom' implementation"<<std::endl;
  }
};
template<typename T>
void foo() {
  algorithm_selector<std::is_abstract<T>::value>::implementation();
}
struct ABC { virtual void bar() const = 0; };
struct Derived : ABC { };
struct Blah {};
int main() {
  foo<ABC>();
  foo<Derived>();
  foo<Blah>();
  return 0;
}

编译为 (gcc 4.8.1) g++ example.cpp -std=c++11产生输出:

I am using the 'custom' implementation
I am using the 'custom' implementation
I am using the default implementation

我喜欢它的是它超越了*enable_if*的基本原理(至少在概念上):它为我提供了可用于在编译时选择任意策略的习语。这可能只是一个偏好问题,但对我来说,这个成语是坚如磐石的。另外,请查看安德烈·亚历山德雷斯库书中描述的政策模式;它们与这种由编译时功能驱动的设计灵活性有关。