【问题标题】:Compile-time singleton more-than-one-time-instantiation detection编译时单例多于一次实例化检测
【发布时间】:2012-09-18 15:02:52
【问题描述】:

是否可以创建一个模板元构造,它可以在第一次(或前 n 次)被调用时采用一个执行路径,如果它被多次调用(超过 n 次)则采用另一个执行路径?

【问题讨论】:

  • @BasileStarynkevitch 一个小例子?请。

标签: c++ templates c++11


【解决方案1】:

没有。模板仅在编译时进行评估。

问题是关于运行时发生的事情(执行路径)。
现在应该很有可能在代码中构建这个结构,但它不是模板元结构(虽然它可以是模板元程序的一部分,但进行测试的代码将是运行时代码(即普通代码) ))。

【讨论】:

  • 但是编译器会优化例如if 带有常量模板参数等。
  • @BasileStarynkevitch:正如您在评论中也逃避(编译器会优化)它无法在运行时评估内容。模板评估仅在编译时完成。
  • 然而,它会优化常量(希望如此)并消除在特定实例中无法到达的路径。但是,指示这是第一个实例还是另一个实例的变量不是常量。
【解决方案2】:

您可以使用模板来实现路径的编译时间决策,就像在这个示例中使用模板专业化:

template <bool whichOne>
class ExecutionExampleImpl;

template <>
class ExecutionExampleImpl<true> {
public:
  static void doIt() {
    std::cout << "Do it for the first time(s)\n";   
  }
};

template <>
class ExecutionExampleImpl<false> {
public:
  static void doIt() {
    std::cout << "Do it for the second time(s)\n";   
  }
};


template <unsigned execution>
void executionExample()
{
   const unsigned ExecutionExampleFirstLimit = 3;

   ExecutionExampleImpl<execution <= ExecutionExampleFirstLimit>::doIt();
}

int main() {
   executionExample<1>();
   executionExample<2>();
   executionExample<3>();
   executionExample<4>();
   executionExample<5>();
   executionExample<6>();
}


但是我相信您更喜欢运行时决策。您可以使用静态局部变量来实现:

void executionExample()
{
   const unsigned ExecutionExampleFirstLimit = 3;
   static unsigned executionCounter = 0;
   if (executionCounter++ <  ExecutionExampleFirstLimit)
   {
      std::cout << "Do it for the first time(s)\n";   
   }
   else
   {
       std::cout << "Do it for the second time(s)\n";   
   }
}

int main() {
   for (unsigned int i = 0; i < 6; ++i)
      executionExample();
}

【讨论】:

  • executionExample() 和 executionExample() 等都是不同的函数。这些函数中的每一个在每次执行时都采用完全相同的路径。
  • @Predrag 对于1,2,3,他们走一条路,而4,5,6,.... 他们走另一条路。参见编译时条件execution &lt;= ExecutionExampleFirstLimit。但实际上,它们是执行一项或其他任务的不同功能。
【解决方案3】:

这个问题与两个明显不相关的事情相匹配:模板由编译器实例化(不是执行),所需的实例在运行时执行 - 机器时间(不是编译器)。

您可以做一个模板,根据常量值进行不同的实例化。如果这些实例是递归的,那么您就有一种“编译时执行”来决定要实例化什么。

std::conditional 是一个很好的示例。

【讨论】:

    【解决方案4】:

    在一般情况下,是否遵循特定路径以及遵循多少次,可以在运行时决定——如果函数调用在if 语句的主体中,举一个明显的例子。然而,任何依赖于模板(及其参数)的指令执行流程的构造都必须在编译时知道这一点。所以不,不能这样做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-04
      • 2023-04-05
      • 1970-01-01
      • 2011-07-02
      • 1970-01-01
      • 2019-11-01
      • 1970-01-01
      相关资源
      最近更新 更多