有人可以向我解释模板解析顺序规则吗?

时间:2011-05-01 15:42:13

标签: c++ templates metaprogramming boost-mpl

好的,这里填写伪代码。

template <typename T>
void fun(/*...*/)
{
    some_meta_typelist pushback T;
}

所以我的想法是,在任何一点上实现这个函数,它都会增长some_meta_typelist对象。如果这是跨越边界完成的,是否有任何保证在类型列表用于MPL :: fold函数之前,将编译对此模板构建机制的所有调用。什么时候进行评估?何时可以确定它们已经完成?这应该仅限于编译单元,而不是跨越.cpp边界吗?是否有相当于使用静态变量调用函数以确保在使用之前创建了对象?

更新

我正在考虑这样一种想法,即调用系统的对象将构建系统需要完成其工作的类型列表。我的感觉是类型列表完全取决于编译顺序,因此不是单个文件CPP之外的有效方法。我知道MSVC按字母顺序编译,或者至少它已经习惯了,所以我可以命名最终文件ZZZZ.cpp,最后我指的是需要完全构建的类型列表的文件。这不是一个安全或兼容的解决方案。是这样的吗?有工作吗?

全部谢谢

1 个答案:

答案 0 :(得分:3)

以下是模板实例化工作原理的简单易懂版本(我将使用Boost documentation for fold)。

假设你是一个C ++编译器(让我们称你为clang ...这是一个非常酷的名字),你很高兴读到.cpp文件以便编译它。您会看到所有这些常规功能,例如void foo()float magic(int x, double p)int main(int argc, char** argv)。然后,你会遇到这样的事情:

template <typename T>
struct is_fun
{
    typedef some_other_type<T> something_else;
    typedef typename something_else::value value;
}

在这里,clang说:很酷,我知道这个名为is_fun的结构,它是一个模型,只有一个类型作为参数。此时,is_fun是未初始化的模板。重要的是要注意它不是在这里编译任何东西。当clang看到模板化的任何东西时,它会检查语法(达到它能够的程度)并继续前进。没有办法在目标代码中发出未初始化的模板 - 它纯粹是C ++而不是编译。

稍后,它出现并看到is_fun在这样的语句中使用:

typedef vector<long,float,short,double,float,long,long double> types;
typedef fold<
             types,
             int_<0>,
             if_< is_fun<_2>,next<_1>,_1 >
            >
        ::type number_of_fun;

现在,clang很懒,只是说“好吧,number_of_fun只是这个可怕事物的别名。”再一次,它不会任何事情。稍后在您的代码中,它会看到:

int foo()
{
    const int fun = number_of_fun::value;
    return fun;
}

现在,它已经对number_of_fun模板做了一些事情。现在,模板参数将填入值(因为使用number_of_fun::value需要它)。 clang将逐步完成所有Boost内容,并最终以您的模板is_fun结束。列表中需要的第一件事是long(这就是折叠矢量的作用),因此它创建了一个基于long的新类型,填充了所有T

struct is_fun<long>
{
    typedef some_other_type<long> something_else;
    static const int value = typename something_else::value;
}

此类 将被编译,因为它已被使用。 C ++模板的基本规则是:在编译期间使用它时,它将被实例化,这意味着它将被编译。在运行时,您无需做任何特别的事情。