| 论坛: AFEPack |
|---|
| 主题: mpi版本AFEPack安装出错 |
|---|
| mpi版本AFEPack安装出错 [帖号 #1151] |
四, 26 八月 2010 00:51 |
royee193 发帖数: 1 注册时间: 七月 2010 地区: 湘大-北大 |
Junior Member |

|
|
=============================================================
请大虾们帮忙,非常感谢!
在自己本本上对最新AFEPack进行安装时,进行make出现错误,就将"library/include"链接到gcc可以找到的路径下,
并将链接名取为"AFEPack", 然后将"library/mpi/include"链接到
"AFEPack/mpi",然后make; 每次都停留在如下位置不动:
Parsing file /home/royee/usr/src/AFEPack/library/src/TemplateElement.vector_value.l3.cpp...
Preprocessing /home/royee/usr/src/AFEPack/library/src/Thread.cpp...
Parsing file /home/royee/usr/src/AFEPack/library/src/Thread.cpp...
Building group list...
Building directory list...
Building namespace list...
Building file list...
Searching for included using directives...
Building class list...
Associating documentation with classes...
Computing nesting relations for classes...
Searching for members imported via using declarations...
Building example list...
Searching for enumerations...
Searching for documented variables...
Building member list...
Searching for friends...
Searching for documented defines...
Computing class inheritance relations...
=============================================================
人生需要不断地努力,让自己的灵魂变得富有。。。
|
|
|
| 主题: 弱弱得问一下,怎么生成一系列由粗到细的四边形网格呢? |
|---|
| 弱弱得问一下,怎么生成一系列由粗到细的四边形网格呢? [帖号 #1140] |
一, 09 八月 2010 20:20 |
tenger 发帖数: 34 注册时间: 七月 2008 |
Member |
|
|
谢谢!
|
|
|
| 主题: 自适应参数 |
|---|
| 自适应参数 [帖号 #888] |
三, 20 五月 2009 04:32 |
juyuefo 发帖数: 19 注册时间: 三月 2009 |
Junior Member |
|
|
mesh_adaptor.convergenceOrder() = 0.; /// 设置收敛阶为0
这个收敛阶干啥用的?
|
|
|
| 主题: ubuntu8.10下旧的deal.II版本不能make呢。新的就可以了。 |
|---|
| ubuntu8.10下旧的deal.II版本不能make呢。新的就可以了。 [帖号 #782] |
一, 30 三月 2009 00:39 |
starskywolf 发帖数: 8 注册时间: 九月 2008 |
Junior Member |

|
|
刚刚安装了ubuntu8.10,装一下AFEPack吧,发现make base lac的时候,过不去。
换成新的就可以了。
|
|
|
| 主题: 求助:如何计算已知标量有限元函数与向量的散度? |
|---|
| 求助:如何计算已知标量有限元函数与向量的散度? [帖号 #584] |
日, 07 九月 2008 03:42 |
hongfeifu 发帖数: 9 注册时间: 九月 2008 |
Junior Member |
|
|
问题就是要计算已知标量有限元函数u_h与向量检验函数v_h的散度的内积?问题见附件,大家帮忙支支招啊!谢谢!
[更新: 日, 13 六月 2010 03:26]
|
|
|
| 主题: AFEPack 源码中一个小问题 |
|---|
| AFEPack 源码中一个小问题 [帖号 #541] |
一, 02 六月 2008 02:39 |
cai_zn 发帖数: 87 注册时间: 十月 2007 |
Member |
|
|
在 AFEPack 源码中文件 FEMSpace.vector_value.templates.h 里,有几处出现如下代码:
std::vector<std::vector<value_type> > val(i, std::vector<value_type>(DIM, 0));
其中 std::vector<value_type>(DIM, 0) 是说用 0 来初始化 vector 里的每个元素,但 value_type 的定义是
#define value_type nVector<vector_length, double>
这个为什么能用 0 来初始化呢?我在 gcc-4.3.0 下没能编译过,把 0 改成 vector_zero 后没问题了。
|
|
|
| 主题: 需要 boost 支持! |
|---|
需要 boost 支持! [帖号 #425] |
日, 16 十二月 2007 19:32 |
robertliecn 发帖数: 259 注册时间: 七月 2007 |
Senior Member |
|
|
重要通告:
现在 cvs snapshot 版本的 AFEPack 中,使用了 boost 的头文件,用来支持在模板单元、自由度和基 函数的描述文件中加入 Shell 脚本风格的注释,请安装的时候先将 boost 头文件加入到编译器可以找到的路径中,比如 /usr/local/include 下,另外, boost 库可以在
http://www.boost.org
处获得。
|
|
|
| 主题: 考考你例子-—给一些提示? |
|---|
|
| 主题: 发帖必看 |
|---|
| 发帖必看 [帖号 #52] |
三, 11 七月 2007 03:02 |
hghdd 发帖数: 83 注册时间: 七月 2007 |
Member |
|
|
1. 当您完成文章时, 请先预览。
由于某种原因, 当符号或者字母紧贴汉字时, 偶尔会出现字符被方框取代的情况, 影响阅读。 这时请检查出现方框的字段, 注意把非中文字符与中文字符之间添加空格, 就可以避免乱码产生。
|
|
|
| 主题: 全下载 |
|---|
| 全下载 [帖号 #18] |
一, 09 七月 2007 04:25 |
YunChen 发帖数: 212 注册时间: 七月 2007 地区: IMR,CAS |
Senior Member |
|
|
正是我想要的,全打印下来,一点一点啃了.
......
非常谢谢提供这些!
|
|
|
| 主题: 再次注册 |
|---|
| 再次注册 [帖号 #3] |
一, 09 七月 2007 02:14 |
YunChen 发帖数: 212 注册时间: 七月 2007 地区: IMR,CAS |
Senior Member |
|
|
很可惜前一段时间的有关AFEPack的安装说明,我 有保存就这样都丢了
还是希望版主再传上去一份啊!!
你们都帮了我这么多了,但是我的安装问题依 存在.
还是非常感谢李老师及其他帮助我的热忱的老 师朋友们!!
真不知道这个AFEPack真的有感情,见了陌生人这 害羞,就是不让我体会AFEM的快乐.
千呼万唤不出来......
再接再厉!
|
|
|
| 论坛: Finite Difference Method |
|---|
| 主题: 有没有比较快的方法去计算这个 Matrix multiplication ? |
|---|
| 有没有比较快的方法去计算这个 Matrix multiplication ? [帖号 #1090] |
二, 06 七月 2010 03:28 |
wllee 发帖数: 12 注册时间: 七月 2007 |
Junior Member |
|
|

正常要 N*N 步才可以算好,
有没有比较快的方法去计算这个 Matrix multiplication ?
|
|
|
| 论坛: Finite Element Method |
|---|
| 主题: 注意到"FreeFEM++"这个软件包了吗? |
|---|
注意到"FreeFEM++"这个软件包了吗? [帖号 #1060] |
二, 27 四月 2010 01:37 |
raymon 发帖数: 4 注册时间: 八月 2009 |
Junior Member |
|
|
这是法国人开发的包,用有限元解二维或三维的各种pde。
使用简单,代码紧凑,可在单个方程绝对在五十行以下。
向大家推荐.....
|
|
|
| 论坛: C/C++ |
|---|
| 主题: GCC 4.5.0 发布 |
|---|
| GCC 4.5.0 发布 [帖号 #1059] |
六, 17 四月 2010 03:49 |
cai_zn 发帖数: 87 注册时间: 十月 2007 |
Member |
|
|
http://gcc.gnu.org/gcc-4.5/changes.html
几个比较吸引我的改进:
1. 引入了 MPC 库,使得编译期的复数运算更加准确;
2. 加入了一个新的链接期优化选项 -flto,这可能使得不同的目标文件中的函数可以相互 inline;
3. 改进了对 C++0x 的支持;
4. 加入了一个 profile mode(这个好像蛮好玩的,但估计对咱们没什么用)。
不知道上面的第2条到底能有多大的优化效果,我在等 GCC 的 rpm 包出来,懒得自己去编译......
|
|
|
| 主题: C++ 0x 学习笔记(九)──delete |
|---|
| C++ 0x 学习笔记(九)──delete [帖号 #1008] |
五, 01 一月 2010 10:59 |
cai_zn 发帖数: 87 注册时间: 十月 2007 |
Member |
|
|
本文谈谈关键字 delete。这里所要说的 delete 并不是用来释放空间的那个 delete,而是指用来禁用某个函数的新的 delete。在上一篇中,我提到了 default 的一个作用是可以方便地使得拷贝操作仅有其友元和自身可以使用,但假如我们要彻底禁用一个类的拷贝操作呢? [1] 中为我们提供了现行标准下的一种做法:
class A {
public:
...
private:
A(const A&);
A& operator=(const A&);
};
这样一写,显然除了友元和其自身,都无法调用复制操作。但如果友元和其自身调用了复制操作,只要我们不写这两个函数的实现,链接器就必然会发出警告。但事实上,我们一般不喜欢让链接器来找错误,因此 [1] 中还提供了一个把错误移到编译期的做法,这里不再赘述。我想说的是,这个禁用拷贝的操作用 delete 可以方便地完成,例如:
class A {
public:
...
A(const A&) = delete;
A& operator=(const A&) = delete;
};
简单地说,delete 就是用于禁用那些编译器自动认为存在的函数,其用法可类比 default。那么到底可以 delete 哪些函数呢? [2] 中给我们举了许多例子,我这里摘抄几个,但稍加变化:
1. 默认构造函数、拷贝构造函数、拷贝构造运算符。这点不展开了,delete 的作用一目了然。
2. new 和 new[] 运算符,例如:
struct A {
void * operator new(std::size_t) = delete;
void * operator new[](std::size_t) = delete;
};
这两行有什么效果我想大家猜也都猜到了,但它有什么用呢?的确,平时我们很少能够用到这样的操作,它的作用是使以 A 为类型的对象不能够在"自由存储区 (free store)"中存在。关于 C++ 中几个存储空间的概念可参见 [3] 中的 Issue #9。这样的操作一般只在用户需要自己管理内存空间时使用。
3. 析构函数,如:
struct A {
~A() = delete;
};
这个看起来更玄妙,不允许对象析构了?!它的作用是只允许以 A 为类型的对象在"自由存储区"中存在,换言之,也就是产生类型为 A 的对象的方式仅可能是
这样的方式,因为其余方式都将导致对对象自动调用析构函数。但它被 new 之后却不能够被 delete,因为那也将导致对对象的析构。好在 C++0x 提供了简单的垃圾回收 (Garbage Collection) 机制,可以用于释放这些空间。当然,这个我们也不会常用...
4. 防止一些不需要的类型转换,如:
struct A {
A(long long);
A(long) = delete;
};
void B(long long);
void B(long) = delete;
这个就不多解释了,大家都看得明白。类似地,delete 还可以用在模版函数上,比如:
struct A {};
struct B : A {};
void f(A&) {}
template <class T> void f(T&) = delete;
int main()
{
A a;
B b;
f(a); // OK!
f(b); // error: deleted function 'void f(T&) [with T = B]'
}
其它的情形请大家自己去看 [2] 吧,上面提到的除了第一条和第四条外已经很不常用了,没提到的就更不常用了。但第一条用来防止对象的拷贝还是很好用的,C++0x 标准模版库中的 std::thread 和 std::unique_ptr 等都用到了它;第四条也很常用,比如 std::unique_ptr 的 reset 成员函数就用到了这一点(参见 [4])。总而言之,delete 其实很简单,就是禁止你所不想要的那些函数。本文下笔时有些过于追求全面,那些平时用不着的东西,大家当作没看见就好了 
参考资料:
[1] Scott Meyers. Effective C++: 55 Specific Ways to Improve Your Programs and Designs (3rd Edition)
[2] Lawrence Crowl. Defaulted and Deleted Functions. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm
[3] Herb Sutter. Guru of the Week. http://www.gotw.ca/gotw/
[4] Alisdair Meredith. Defect Report 821. http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#821
|
|
|
| 主题: C++0x 中的多线程 第二部分:启动带函数对象和参数的线程 |
|---|
| C++0x 中的多线程 第二部分:启动带函数对象和参数的线程 [帖号 #956] |
六, 10 十月 2009 22:34 |
cai_zn 发帖数: 87 注册时间: 十月 2007 |
Member |
|
|
[翻译自 http://www.justsoftwaresolutions.co.uk/threading/multithreading-in-c++0x-part-2-function-objects-and-arguments.html]
这是介绍新 C++0x 线程库的系列博文中的第二篇。第一篇所介绍的是对简单函数在 C++0x 中启动线程。
如果你读过本系列的第一部分,你应该已经看到在 C++0x 中启动一个线程有多简单了:只需要构造一个 std::thread 实例并传入你希望在新线程上运行的函数即可。这虽然很好,但如果新线程仅能够运行无参数的普通函数的话,所受的限制未免也太大了----所有需要的信息都必须以全局变量的形式传入,这将会无比的混乱。还好,事实上情况不是这样,在新的线程上,你不仅能够像运行普通函数一样运行函数对象,还能够传入参数。
在另一线程上运行一个函数对象
与 C++ 标准库的其它部分相一致,你并不限于在启动线程时调用普通函数----std::thread 的构造函数还可以以实现了函数调用运算符的类实例为参数来调用。我们来通过一个函数对象来输出"hello":
#include <thread>
#include <iostream>
class SayHello
{
public:
void operator()() const
{
std::cout<<"hello"<<std::endl;
}
};
int main()
{
std::thread t((SayHello()));
t.join();
}
你可能会对 SayHello 构造函数调用之外的那对小括号感到奇怪,这是为了防止所谓 C++ 最烦人的分析机制:没有那对小括号的话,这行会被当作是对一个以无参数并返回 SayHello 对象的函数指针为参数,并返回 std::thread 对象的函数的声明,而不是一个以 std::thread 为类型的对象。还有一些其它方法来避免此问题。首先,你可以创建一个有名字的 SayHello 类型变量,并将它送给 std::thread 的构造函数:
int main()
{
SayHello hello;
std::thread t(hello);
t.join();
}
其次,你可以使用复制构造函数(译注:这里事实上使用的是移动语义,据标准草案 30.3.1 节,std::thread 对象不允许复制):
int main()
{
std::thread t=std::thread(SayHello());
t.join();
}
最后,如果你使用的是一个完全的 C++0x 编译器,你还可以使用新的初始化语法,也就是用花括号代替小括号:
int main()
{
std::thread t{SayHello()};
t.join();
}
这样就和我们的第一个例子中使用两重小括号的形式完全等价了。
好的,初始化已经说得够多了。不管你采用哪种方法,目的是一样的:把你的函数对象复制到新线程能够访问的某个内部存储空间中,让新线程去调用 operator()。当然,你的类可以拥有成员变量和其它的成员函数,于是一种把数据传入线程函数的方法就是:把它以构造函数参数的形式传入,并以成员数据的形式存储:
#include <thread>
#include <iostream>
#include <string>
class Greeting
{
std::string message;
public:
explicit Greeting(std::string const& message_):
message(message_)
{}
void operator()() const
{
std::cout<<message<<std::endl;
}
};
int main()
{
std::thread t(Greeting("goodbye"));
t.join();
}
在这个例子中,我们的消息以成员变量的形式存储在类中,因此当 Greeting 实例被复制到线程中的时候,那条消息也被复制了。于是这个程序将会输出"goodbye"而不是"hello"。
这个例子还给出了一种在除了将需要调用的函数本身之外再往新线程里传其它信息的方法----将它作为函数对象的数据成员。如果这些数据对函数对象本身来说有意义,那么这是个理想的办法,否则的话,我们还需要其它的技术。
给线程函数传参数
正如我们方才所见,一种给线程函数传参数的方法就是把它们封装到一个含有函数调用运算符的类中。事实上,我们并不需要每次都写个特殊的类,标准库为我们提供了进行这项操作的简单方法,那就是使用 std::bind。std::bind 函数模板可以接受可变数量的参数,其中第一个总是一个带参数的函数或可调用对象,其余的则是调用函数是需要传入的参数。函数输出是一个函数对象,它存储了我们所提供的参数的复本,其函数调用运算符则调用那个被绑定的函数。因此,我们可以用它来给新线程传入要输出的消息:
#include <thread>
#include <iostream>
#include <string>
#include <functional>
void greeting(std::string const& message)
{
std::cout<<message<<std::endl;
}
int main()
{
std::thread t(std::bind(greeting,"hi!"));
t.join();
}
这样很好,但我们可以做得更好----我们可以把参数直接传进 std::thread 的构造函数里,这样它们就会被复制到新线程的内部存储空间中并提供给线程函数。这样,我们就可以更简单地写出前一个例子:
#include <thread>
#include <iostream>
#include <string>
void greeting(std::string const& message)
{
std::cout<<message<<std::endl;
}
int main()
{
std::thread t(greeting,"hi!");
t.join();
}
这样不仅代码更简单了,它可能还会更高效,因为我们所提供的参数被直接复制到了线程的内部存储空间中,而不是先送给那个由 std::bind 生成的对象,然后再复制到线程的内部存储空间中。
对于多个参数的情况,只要把其余的参数也都放进 std::thread 的构造函数即可:
#include <thread>
#include <iostream>
void write_sum(int x,int y)
{
std::cout<<x<<" + "<<y<<" = "<<(x+y)<<std::endl;
}
int main()
{
std::thread t(write_sum,123,456);
t.join();
}
std::thread 的构造函数是个可变模板,因此它可以接受编译器内部限制范围之中的任意多个参数。但如果你需要给你的线程函数传入许多参数的话,你可能更需要重新考虑一下设计上的问题。
接下来
线程启动的问题还没完呢----关于传参数还有些细致微妙的内容我们没有介绍。在本系列的第三部分中,我们将看到如何传入引用,以及使用类成员函数作为线程函数。
试试吧
如果你正在使用 Microsoft Visual Studio 2008 或者 Ubuntu Linux 上的 g++ 4.3,你可以使用 just::thread 对新的 C++0x 线程库的实现在尝试本系列中的例子。
|
|
|
| 主题: C++0x 中的多线程 第一部分:启动线程 |
|---|
| C++0x 中的多线程 第一部分:启动线程 [帖号 #955] |
六, 10 十月 2009 22:24 |
cai_zn 发帖数: 87 注册时间: 十月 2007 |
Member |
|
|
[翻译自 http://www.justsoftwaresolutions.co.uk/threading/multithreading-in-c++0x-part-1-starting-threads.html]
这是介绍新 C++0x 线程库的系列博文中的第一篇。
并发运行和多线程就是指并行地运行多份代码。如果你有像一个精细闪亮的多核 CPU 或者一个多处理器系统一样支持并行的硬件,那么这样的代码就真正地能够并发运行,否则操作系统会让它们交替执行----时而执行某个任务,时而又执行另一个。这些都没问题,但你必须以某种方式指定所有线程上所运行的代码。
存在一些高层次的建构,比如说英特尔的 Threading Building Blocks 中的并行算法,它们能够为你做好各线程对代码的分割,但 C++0x 中不包含这些。相反,我们得自己来控制线程,用来实现它的工具就是 std::thread。
在另一个线程上运行一个简单函数
我们首先要在另一个线程上运行一个简单的函数。为做到这一点,我们需要创建一个新的 std::thread 对象,并把要运行的函数传给构造函数。std::thread 在头文件 <thread> 里,因此我们最好先包含它。
#include <thread>
void my_thread_func()
{}
int main()
{
std::thread t(my_thread_func);
}
如果你编译并运行该程序,它并不会做什么事:虽然它启动了一个新的线程,但线程函数是个空函数。现在我们让它做点儿什么,比如打印一个"hello":
#include <thread>
#include <iostream>
void my_thread_func()
{
std::cout<<"hello"<<std::endl;
}
int main()
{
std::thread t(my_thread_func);
}
如果你编译并运行这个程序,会发生些啥呢?它会如我们所期待的那样打印出 hello 吗?呃,实际上这个不一定,可能会也可能不会。我在我的机器上运行了若干次,结果是不同的:有时打印出 hello 和一个换行,有时打印出 hello 但没有换行,有时什么都不输出。这是怎么回事?如此简单程序的行为难道不应该理所当然是可预料的么?
等待线程结束
确实,其结果就应当是不可预料的,这个程序并无可预期的行为。问题在于我们并没有等待线程结束。当程序执行到 main() 函数的末尾时,整个程序就终止了,它并不管其它线程正在干什么。由于线程安排是不可预期的,我们无法知道另一个线程执行到哪儿了,它可能已经运行完了,可能只输出了"hello",但还没处理 std::endl,也可能都还没开始。不论是哪种情况,当程序退出时它都将立即停止。
如果我们要保证输出我们的信息,就必须保证线程运行结束。为此,我们通过调用 thread 对象的 join() 成员函数来实现线程合并:
int main()
{
std::thread t(my_thread_func);
t.join();
}
现在,main() 函数会在退出前等待线程结束,这样每次执行程序都会输出 hello 并跟一个换行符。这里强调一个一般性的观点:如果你希望保证线程在你的代码中某个特定的位置一定结束,你就必须得去等待它。这不仅是为了保证当程序退出时所有线程都结束,当线程能够存取局部变量时,这点也极为重要,因为我们必须保证当局部变量离开其作用域时,线程一定结束。
接下来
在本文中,我们已经看到如何在一个单独的线程上运行简单的函数并等待线程结束。然而,当你要启动一个线程时你不可能仅局限于这种不带参数的简单函数。在本系列的第二部分中,我们将会看到如何启动一个线程来执行函数对象,以及如何将参数传入。
试试吧
如果你正在使用 Microsoft Visual Studio 2008 或者 Ubuntu Linux 上的 g++ 4.3,你可以使用 just::thread 对新的 C++0x 线程库的实现在尝试本系列中的例子。
|
|
|
| 主题: C++0x Concepts 死了…… |
|---|
| C++0x Concepts 死了…… [帖号 #906] |
二, 18 八月 2009 21:00 |
cai_zn 发帖数: 87 注册时间: 十月 2007 |
Member |
|
|
发生在一个多月前的事情,我居然昨天才得到 消息…… 这个曾经被认为是 C++0x 最重要的也最令人兴奋的特性最终还是被投票 否决了,而且好多人认为 Concepts 的回归不会是短期内的事情。感兴趣的朋友们 自己去 Google 找 "C++0x Concepts" 吧,相关的文章太多了。
而这样一来,目前已写好的标准内容也要再经 历一番大的改动,C++0x 至少也要到 2010 年才能完成了。尽管去掉了一个重要内容,C++ 0x 对 C++98 以及其修订版本 C++03 的改进还是很大的。当然,我们还是希望在 2016 年左右(Bjarne Stroustrup 的估计)的新标准中能够看到 Concepts 的回归。
|
|
|
| 主题: C++ 0x 学习笔记(七)──decltype |
|---|
| C++ 0x 学习笔记(七)──decltype [帖号 #881] |
五, 15 五月 2009 05:00 |
cai_zn 发帖数: 87 注册时间: 十月 2007 |
Member |
|
|
decltype 的全称是 declared type,我不知道怎么翻译,所以在标题中就直 接那么写了。大家可能听说过 GCC 的一个扩展叫 typeof,这可以取出某个变量的类型。比如在 C 中
#define MAX(a, b, result) ((result) = (a) > (b) ? (a) : (b))
就可以写成
#define MAX(a, b, result) {
typeof(a) c = (a); typeof(b) d = (b);
(result) = (c > d ? c : d);
}
以避免 MAX(i++, j++, m) 这样的使用方式带来的问题。在 C++0x 中,这个扩展被标准化,但把名字改了,变为 decltype。它的使用方法也很容易理解,比如
struct T { int a; };
T t1;
T &t2 = t1;
const T &t3 = t1;
decltype(t3) t4 = t2; // t4 具有类型 const T &
decltype(t1->a) a1 = t1->a; // a1 具有类型 int
decltype(t2->a) a2 = t1->a; // a2 具有类型 int &
decltype(t3->a) a3 = t1->a; // a3 具有类型 const int &
当然,decltype 判断类型的详细规则有很多,这里就不一一列 出了,要弄清楚的同学可以参考 [1]。然而 decltype 还有一个好用的地方,就是上一篇中提到的程 序返回值中的 auto。来看这一个例子:
template <class T1, class T2, class T3>
auto area(const T1 &a, const T2 &b, const T3 &c)
-> decltype(sqrt(a + b + c))
{
typedef decltype(sqrt(a + b + c)) T;
T s = (a + b + c) / 2;
return sqrt(s * (s - a) * (s - b) * (s - c));
}
这也是我们在 C++03 中找不到的语法。它允许函数的返回值类型为 auto,然后在函数的参数表结束后通过“->”符号给出函数类型。例如:
则函数 f() 具有返回值 int。事实上不用 auto 也行,上面那个求面积的函数可以写成
template <class T1, class T2, class T3>
decltype(sqrt((*(T1*)0) + (*(T2*)0) + (*(T3*)0)))
area(const T1 &a, const T2 &b, const T3 &c);
但显然原来那种将 auto 和 decltype 结合起来的写法看起来更顺眼一些。当然 decltype 所做出的类型推导都是编译时所做的,所以不 用担心程序效率以及数组越界等问题,例如对 于指针 a 可以随意地写 decltype(a[1000])。
至此为止,我想让这个系列先告一段落,因为 在目前 GCC 已经实现的范围内,我并没有看到其它更令用 户激动人心的新特性。我写这个只是想通过一 些例子让大家能看到那些新语法最简单的用法 ,并不想要全面地介绍它们。而等哪天 GCC 把 concepts 和 lambda 表达式实现得差不多了,我再继续写下去。
参考资料:
[1] Jaakko Järvi, Bjarne Stroustrup, Gabriel Dos Reis. Decltype (revision 7): proposed wording. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n234 3.pdf
[2] Jason Merrill. New Function Declarator Syntax Wording. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n254 1.htm
|
|
|
| 主题: C++ 0x 学习笔记(五)——列表初始化 |
|---|
| C++ 0x 学习笔记(五)——列表初始化 [帖号 #867] |
六, 02 五月 2009 03:59 |
cai_zn 发帖数: 87 注册时间: 十月 2007 |
Member |
|
|
C++ 中所使用的各种容器与 C 相比,一个很不方便的地方就在于初始化。但 C++0x 中改善了这一点,这个看看 C++0x FAQ [1] 中给的几个例子就很清楚了:
vector<double> v = { 1, 2, 3.456, 99.99 };
list<pair<string,string>> languages = {
{"Nygaard","Simula"}, {"Richards","BCPL"}, {"Ritchie","C"}
};
map<vector<string>,vector<int>> years = {
{ {"Maurice","Vincent", "Wilkes"},{1913, 1945, 1951, 1967, 2000} },
{ {"Martin", "Ritchards"}, {1982, 2003, 2007} },
{ {"David", "John", "Wheeler"}, {1927, 1947, 1951, 2004} }
};
有了这一招,初始化一个容器就变得和数组一 样方便了。这里顺便提一下,C++0x 中不再要求写 vector<vector<double> > 了,N1757 提案 [2] 中已经给出了解决方案,它要求模版参数中的 > 和 >> 运算符必须加括号 ()。另外,初始化中可以不要那个等号,也就 写成
vector<double> v{ 1, 2, 3.456, 99.99 };
现在的问题是,这样的初始化是怎么实现的呢 ?
事实上很简单,C++0x 中遇到一个用大括号括起来的列表时,会把它 翻译成 std::initializer_list<T> 类型的一个对象。例如,当有了以下这个函数 后:
void f(initializer_list<int> args)
{
for (auto p=args.begin(); p!=args.end(); ++p) cout << *p << "\n";
}
我们就可以写:
这样的代码了。这个例子仍然来自 [1],因为我想不出更简单的了。注意其中 auto 是自动类型推导的关键字,这里就相当于 initializer_list<int>::iterator。这个以后我们单独说。进一步,如 果我们有
void g(const vector<int> &v);
那么就可以写:
这部分内容比较简单,今天就写这么多吧。最 后展示一下 initializer list 的另一个好用之处,也来自 [1]:
for (const auto x : { 1,2,3,5,8,13,21,34 }) cout << x << '\n';
大家可以想象一下会在标准输出流中输出什么 哦!
参考资料:
[1] Bjarne Stroustrup. C++0x - the next ISO C++ standard. http://www.research.att.com/~bs/C++0xFAQ.html
[2] Daveed Vandevoorde. Right Angle Brackets. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n175 7.html
[3] Jason Merrill, Daveed Vandevoorde. Initializer List proposed wording. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n267 2.htm
|
|
|
| 主题: C++ 0x 学习笔记(三)──右值引用 (2) |
|---|
| C++ 0x 学习笔记(三)──右值引用 (2) [帖号 #856] |
二, 28 四月 2009 06:34 |
cai_zn 发帖数: 87 注册时间: 十月 2007 |
Member |
|
|
前面提到,右值引用的另外一个作用是“完美 转发” (Perfect forwarding)。考虑 AFEPack 中 Function 这个类的作用,它使得许许多多的函数被包含 到一个统一的框架之中,最终以一个参数的形 式表现出来,这使得许多不同的函数可以用统 一的方式进行处理。现在我们考虑简单一点的 情况,下面这个函数也具有类似的功能:
template <class T, class A1, class A2>
void f(T *g, A1 &a1, A2 &a2)
{
return (*g)(a1, a2);
}
乍一看,这个函数好像把所有无返回值的双参 数函数全都包含了,对于某个具有如下形式原 型的函数 g(其中 T1, T2 可以是引用):
只要调用
就可以实现 g 的功能了。但有时候我们会遇到一些麻烦,比 如对于
void g(const int &a1, int &a2);
会得到以下的结果:
int a;
g(1, a); // 正确!
f(&g, 1, a); // 编译错误!
其原因应该不用我多嘴了。这样看来,要真正 实现 f 的包装功能,我们得写:
template <class T, class A1, class A2> void f(T *g, A1 &a1, A2 &a2) { return (*g)(a1, a2); }
template <class T, class A1, class A2> void f(T *g, const A1 &a1, A2 &a2) { return (*g)(a1, a2); }
template <class T, class A1, class A2> void f(T *g, A1 &a1, const A2 &a2) { return (*g)(a1, a2); }
template <class T, class A1, class A2> void f(T *g, const A1 &a1, const A2 &a2) { return (*g)(a1, a2); }
够麻烦的吧!在 C++03 标准中,我们的确只能这么做,可想而知,假 如我要绑定十个参数呢?
现在大家应该已经猜到右值引用在其中发挥的 作用了吧,现在我们只要写一个函数即可:
template <class T, class A1, class A2>
void f(T *g, A1 &&a1, A2 &&a2)
{
return (*g)(a1, a2);
}
这里这们正好利用了右值引用能与 non-const 右值绑定这一特性,完美地把 f 的参数转发给了 g,这就是右值引用的另一个重要作用了,对 于泛型编程来说,这能减少不少工作量呢!事 实上,为了明确说明我们要在这里做转发,标 准中提供了一个 std::forward 函数来做显式的说明,也就是说我们的代码可 写为
template <class T, class A1, class A2>
void f(T *g, A1 &&a1, A2 &&a2)
{
return (*g)(std::forward<A1>(a1), std::forward<A2>(a2));
}
据 [2] 中所述,在这里 std::forward 仅仅是为了强调语义,它的定义可能是这个样 子的:
template <class T>
struct identity
{
typedef T type;
};
template <class T>
T&& forward(typename identity<T>::type&& a)
{
return a;
}
参考资料:
[1] Peter Dimov, Howard E. Hinnant, Dave Abrahams. The Forwarding Problem: Arguments. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n138 5.htm
[2] Howard E. Hinnant, Bjarne Stroustrup, Bronek Kozicki. A Brief Introduction to Rvalue References. http://www.artima.com/cppsource/rvalue.html
[更新: 二, 28 四月 2009 11:02]
|
|
|
| 主题: 发帖必看 |
|---|
| 发帖必看 [帖号 #53] |
三, 11 七月 2007 03:03 |
hghdd 发帖数: 83 注册时间: 七月 2007 |
Member |
|
|
1. 当您完成文章时, 请先预览。
由于某种原因, 当符号或者字母紧贴汉字时, 偶尔会出现字符被方框取代的情况, 影响阅读。 这时请检查出现方框的字段, 注意把非中文字符与中文字符之间添加空格, 就可以避免乱码产生。
[更新: 三, 11 七月 2007 03:38]
|
|
|
| 论坛: Linux |
|---|
| 主题: 对自己的 Linux 知识有信心的朋友们来此看看 |
|---|
|
| 主题: sed 使用的一个实例 |
|---|
| sed 使用的一个实例 [帖号 #135] |
二, 31 七月 2007 21:33 |
jwzhang 发帖数: 3 注册时间: 七月 2007 |
Junior Member |
|
|
通常我们生产i.e. run_Pattition_16_t_0001.log的文件:内容如下
t = 1.9600000000000015e-01, error = (5.7762673672190665e-02 8.0638641037007019e-02 5.7762673672190047e-02 8.0638641037000636e-02)
step = 0, error = 1.8118950629601327e-01
step = 1, error = 0.0000000000000000e+00
我们想要如下数据 以便用matlab, octave 等把他们的数据读出plot
5.7762673672190665e-02 8.0638641037007019e-02 5.7762673672190047e-02 8.0638641037000636e-02
通过如下操作即可:
grep ^t grep ^t run_Pattition_16_t_0001.log | tr -d "tro=()," | sed -e "s/e / /g" >a.dat
有些空格不能省落呀,我这个菜鸟开始很会出 错的。
这样就会生成 a.dat文件, 里面的数据如下
5.7762673672190665e-02 8.0638641037007019e-02 5.7762673672190047e-02 8.0638641037000636e-02
|
|
|
| 主题: 发帖必看 |
|---|
| 发帖必看 [帖号 #54] |
三, 11 七月 2007 03:03 |
hghdd 发帖数: 83 注册时间: 七月 2007 |
Member |
|
|
1. 当您完成文章时, 请先预览。
由于某种原因, 当符号或者字母紧贴汉字时, 偶尔会出现字符被方框取代的情况, 影响阅读。 这时请检查出现方框的字段, 注意把非中文字符与中文字符之间添加空格, 就可以避免乱码产生。
[更新: 三, 11 七月 2007 03:38]
|
|
|
| 论坛: Moving Mesh Method |
|---|
| 主题: 弱弱的建议 |
|---|
| 弱弱的建议 [帖号 #732] |
五, 02 一月 2009 23:00 |
myjava 发帖数: 7 注册时间: 一月 2009 地区: |
Junior Member |
|
|
|
能否开一个matrix computation & multigrid 的版本呢?
|
|
|
| 主题: 程序问题 |
|---|
| 程序问题 [帖号 #639] |
二, 18 十一月 2008 21:47 |
bluebaby 发帖数: 9 注册时间: 十一月 2008 地区: 广州 |
Junior Member |
|
|
|
用移动网格求解一个二维的Buckly-Levertt方程, 是算不出来,请教一下问题在哪。谢谢。
|
|
|
| 论坛: Eight Diagrams |
|---|
| 主题: 奥运期间注意安全啊!!! |
|---|
| 奥运期间注意安全啊!!! [帖号 #569] |
三, 06 八月 2008 07:36 |
hghdd 发帖数: 83 注册时间: 七月 2007 |
Member |
|
|
|
又一城发现土制炸弹了,恐怖啊。 大家都注意安全!
|
|
|
| 主题: 签个到 |
|---|
| 签个到 [帖号 #145] |
三, 08 八月 2007 05:39 |
crazyfish 发帖数: 15 注册时间: 七月 2007 |
Junior Member |
|
|
好几天没来灌水了,签个到,哈哈
|
|
|
| 主题: 发帖必看 |
|---|
| 发帖必看 [帖号 #108] |
五, 20 七月 2007 23:06 |
hghdd 发帖数: 83 注册时间: 七月 2007 |
Member |
|
|
1. 当您完成文章时, 请先预览。
由于某种原因, 当符号或者字母紧贴汉字时, 偶尔会出现字符被方框取代的情况, 影响阅读。 这时请检查出现方框的字段, 注意把非中文字符与中文字符之间添加空格, 就可以避免乱码产生。
|
|
|
| 主题: HoHo, 1324 |
|---|
| HoHo, 1324 [帖号 #99] |
三, 18 七月 2007 08:33 |
hghdd 发帖数: 83 注册时间: 七月 2007 |
Member |
|
|
AFEPack 版的最高点击率, 1324次! 可喜可贺啊
|
|
|
| 论坛: OpenDX |
|---|
| 主题: 求助:调整轮廓的透明度 |
|---|
| 求助:调整轮廓的透明度 [帖号 #929] |
一, 14 九月 2009 21:02 |
worldsf 发帖数: 13 注册时间: 八月 2009 地区: 武汉 |
Junior Member |

|
|
我要画一个管子里的流线,希望把管子的轮廓 加上去,再做透明处理,以求在显示流线的时 候有管子的轮廓。
请高人指点。
|
|
|
| 主题: 求助:画流线遇到的问题 |
|---|
| 求助:画流线遇到的问题 [帖号 #923] |
五, 04 九月 2009 22:46 |
worldsf 发帖数: 13 注册时间: 八月 2009 地区: 武汉 |
Junior Member |

|
|
我在画流线的时候老是会报错,
EREOE:Streamline:Bad paramtere:data must be a field,muitigrid or composite field.
附带我的*.dx文件
请高手指点指点
|
|
|
| 主题: 求助:如何在 opendx 添加 antialias tools ? |
|---|
| 求助:如何在 opendx 添加 antialias tools ? [帖号 #605] |
一, 13 十月 2008 23:39 |
allawwp 发帖数: 1 注册时间: 十月 2008 |
Junior Member |
|
|
|
没有内容!
|
|
|
| 论坛: CVS |
|---|
| 主题: cvs地址改了吗? |
|---|
| cvs地址改了吗? [帖号 #1005] |
日, 20 十二月 2009 21:20 |
starskywolf 发帖数: 8 注册时间: 九月 2008 |
Junior Member |

|
|
|
大家好,我怎么用不了了?
|
|
|
| 论坛: 公告 |
|---|
| 主题: 系统升级到2.8.1版 |
|---|
系统升级到2.8.1版 [帖号 #930] |
二, 15 九月 2009 02:15 |
robertliecn 发帖数: 259 注册时间: 七月 2007 |
Senior Member |
|
|
|
我们的论坛刚刚升级到了FUDForum 2.8.1版本,如果您在使用的时候有什么问题请尽快告诉我。
|
|
|
| 论坛: TeX |
|---|
| 主题: 请教一下,关于 \tableofcontents 出错 |
|---|
| 请教一下,关于 \tableofcontents 出错 [帖号 #876] |
日, 10 五月 2009 23:18 |
lianyijiang 发帖数: 21 注册时间: 四月 2009 |
Junior Member |
|
|
这个是代码
\documentclass[a4paper]{article}
\usepackage{CJKutf8}
\usepackage{cases}
\usepackage{graphicx}
\usepackage{amsfonts}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{fancyhdr}
\usepackage{indentfirst}
\usepackage{titlesec}
\usepackage{float}
\begin{document}
\begin{CJK}{UTF8}{hei}
\pagestyle{fancy}
\fancyhf{}
\lhead{\bfseries Peking University}
\rhead{北京大学}
\lfoot{\ttfamily Dept.~of Math.}
\rfoot{数学系}
\cfoot{\thepage}
\renewcommand{\headrulewidth}{0.6pt}
\renewcommand{\footrulewidth}{0.4pt}
\pagenumbering{Roman}
你好吗
\tableofcontents
\newpage
\section{程序}
呵呵,这个是程序
\section{原理}
开始阐述原理
\end{CJK}
\end{document}
使用 latex 编译的时候出现这样的错误,这个是为什么呢 ?当我把 \tableofcontents 去掉,就没有这个错误了。
! Package inputenc Error: Unicode char \u 8:程 not set up for use with LaTeX.
See the inputenc package documentation for explanation.
[更新: 日, 10 五月 2009 23:19]
|
|
|
| 论坛: Doxygen |
|---|
| 主题: 发emacs 的Doxygen插件 |
|---|
| 发emacs 的Doxygen插件 [帖号 #375] |
日, 18 十一月 2007 23:50 |
weibo 发帖数: 3 注册时间: 七月 2007 地区: 北京大学 63#118 |
Junior Member |

|
|
|
使用看readme!
|
|
|
| 主题: 推荐一个 vim 的 Doxygen 插件 |
|---|
| 推荐一个 vim 的 Doxygen 插件 [帖号 #373] |
日, 18 十一月 2007 11:38 |
cai_zn 发帖数: 87 注册时间: 十月 2007 |
Member |
|
|
名字叫 DoxygenToolkit,可以在 http://www.vim.org/scripts/script.php?script_id=987 下载到,由于实在是太小了,我直接上传了上 来。这个插件使用起来非常方便,今天很开心 地给自己以前写的一个软件的几个头文件都加 了这样的注释并生成了文档,给不懂这个的人 看看真的很唬人
|
|
|
| 论坛: Make |
|---|
| 主题: (ZZ) GNU Make 中文手册 -- Makefile 的条件执行 |
|---|
| (ZZ) GNU Make 中文手册 -- Makefile 的条件执行 [帖号 #109] |
五, 20 七月 2007 23:19 |
hghdd 发帖数: 83 注册时间: 七月 2007 |
Member |
|
|
经作者同意, 转载自 http://xhbdahai.cublog.cn/
第七章:Makefile 的条件执行
条件语句可以根据一个变量的值来控制make 执行或者忽略Makefile 的特定部分。条件语句可以是两个不同变量、 或者变量和常量值的比较。要注意的是: 条件语句只能用于控制make 实际执行的makefile 文件部分,它不能控制规则的shell 命令执行过程。 Makefile 中使用条件控制可以做到处理的灵活性和高效 性。
7.1 一个例子
首先我们来看一个使用条件判断的Makefile 例子; 对变量“CC” 进行判断,其值如果是“gcc” 那么在程序连接时使用库“libgnu.so” 或者“libgnu.a”, 否则不链接任何库。 Makefile 中的条件判断部分如下:
……
libs_for_gcc = -lgnu
normal_libs =
……
foo: $(objects)
ifeq ($(CC),gcc)
$(CC) -o foo $(objects) $(libs_for_gcc)
else
$(CC) -o foo $(objects) $(normal_libs)
endif
……
例子中,条件语句中使用到了三个关键字:“ ifeq”、 “else” 和“endif”。 其中:
1. “ifeq” 表示条件语句的开始,并指定了一个比较条件 (相等)。 之后是用圆括号括包围的、 使用逗号“,” 分割的两个参数,和关键字“ifeq” 用空格分开。参数中的变量引用在进行变量值 比较时被展开。“ifeq” 之后就是当条件满足make 需要执行的,条件不满足时忽略。
2. “else” 之后就是当条件不满足时的执行部分。不是所 有的条件语句都需要此部分。
3. “endif” 表示一个条件语句的结束,任何一个条件表达 式都必须以“endif” 结束。
通过上边的例子我们可以了解到。Makefile 中,条件表达式工作于文本级别(条件判断处 理为文本级别的处理过程), 条件的解析是由make 来完成的。make 是在读取并解析Makefile 时根据条件表达式忽略条件表达式中的某一个 文本行,解析完成后保留的只有表达式满足条 件所需要执行的文本行。上例,make 处理条件的过程:
当变量“CC” 的值为“gcc” 时,整个条件表达式等效于:
foo: $(objects)
$(CC) -o foo $(objects) $(libs_for_gcc)
当变量“CC” 值不等于“gcc” 时等效于:
foo: $(objects)
$(CC) -o foo $(objects) $(normal_libs)
上面的例子,一种更简洁实现方式:
libs_for_gcc = -lgnu
normal_libs =
ifeq ($(CC),gcc)
libs=$(libs_for_gcc)
else
libs=$(normal_libs)
endif
foo: $(objects)
$(CC) -o foo $(objects) $(libs)
7.2 条件判断的基本语法
一个简单的不包含“else” 分支的条件判断语句的语法格式为:
CONDITIONAL-DIRECTIVE
TEXT-IF-TRUE
endif
表达式中“TEXT-IF-TRUE” 可以是若干任何文本行,当条件为真时它就将 被make 作为需要执行的一部分。当条件为假时,不作 为需要执行的一部分。
包含“else” 的复杂一点的语法格式为:
CONDITIONAL-DIRECTIVE
TEXT-IF-TRUE
else
TEXT-IF-FALSE
endif
表示了如果条件为真,则将“TEXT-IF-TRUE” 作为执行Makefile 的一部分,否则将“TEXT-IF-FALSE” 作为执行的Makefile 的一部分。 和“TEXT-IF-TRUE” 一样,“TEXT-IF-FALSE” 可以是若干任何文本行。
条件判断语句中“CONDITIONAL-DIRECTIVE” 对于上边的两种格式都是同样的。可以是以下 四种用于测试不同条件的关键字。
7.2.1 关键字 “ifeq”
此关键字用来判断参数是否相等,格式如下:
`ifeq (ARG1, ARG2)'
`ifeq 'ARG1' 'ARG2''
`ifeq "ARG1" "ARG2"'
`ifeq "ARG1" 'ARG2''
`ifeq 'ARG1' "ARG2"'
替换展开“ARG1” 和“ARG1” 后,对它们的值进行比较。如果相同则(条件 为真) 将“TEXT-IF-TRUE” 作为make 要执行的一部分,否则将“TEXT-IF-FALSE” 作为make 要执行的一部分(上边的第二种格式)。
通常我们会使用它来判断一个变量的值是否为 空(不是任何字符)。 参数值可能是通过引用变量或者函数得到的, 因而在展开过程中可能造成参数值中包含空字 符(空格等)。 一般在这种情况时我们使用make 的“strip” 函数来对它变量的值进行处理,去掉其中的空 字符。格式为:
ifeq ($(strip $(foo)),)
TEXT-IF-EMPTY
endif
这样,即就是在“$(foo)” 中存在若干前导和结尾空格,“TEXT-IF-EMPTY” 也会被作为Makefile 需要执行的一部分。
7.2.2 关键字 “ifneq”
此关键字是用来判断参数是否不相等,格式为 :
`ifneq (ARG1, ARG2)'
`ifneq 'ARG1' 'ARG2''
`ifneq "ARG1" "ARG2"'
`ifneq "ARG1" 'ARG2''
`ifneq 'ARG1' "ARG2"'
关键字“ifneq” 实现的条件判断语句和“ifeq” 相反。首先替换并展开“ARG1” 和“ARG1”, 对它们的值进行比较。如果不相同(条件为真 ) 则将“TEXT-IF-TRUE” 作为make 要执行的一部分,否则将“TEXT-IF-FALSE” 作为make 要执行的一部分。
7.2.3 关键字 “ifdef”
关键字“ifdef” 用来判断一个变量是否已经定义。格式为:
`ifdef VARIABLE-NAME'
如果变量“VAEIABLE_NAME” 的值非空(在Makefile 中没有定义的变量的值为空), 那么表达式为真,将“TEXT-IF-TRUE” 作为make 要执行的一部分。否则,表达式为假,如果存 在“TEXT-IF-FALSE”, 就将它作为make 要执行一部分。当一个变量没有被定义时,它 的值为空。“VARIABLE-NAME” 可以是变量或者函数的引用。
对于“ifdef” 需要说明的是: ifdef 只是测试一个变量是否有值,不会对变量进行 替换展开来判断变量的值是否为空。对于变量 “VARIABLE-NAME”, 除了“VARIABLE-NAME=” 这种情况以外,使用其它方式对它的定义都会 使“ifdef” 返回真。就是说,即使我们通过其它方式(比 如,定义它的值引用了其它的变量) 给它赋了一个空值,“ifdef” 也会返回真。我们来看一个例子:
例1:
bar =
foo = $(bar)
ifdef foo
frobozz = yes
else
frobozz = no
endif
例2:
foo =
ifdef foo
frobozz = yes
else
frobozz = no
endif
例1中的结果是:“frobozz = yes”; 而例2 的结果是:“frobozz = no”。 其原因就是在例1 中,变量“foo” 的定义是“foo = $(bar)”。 虽然变量“bar” 的值为空,但是“ifdef” 判断的结果是真。因此当我们需要判断一个变 量的值是否为空的情况时,需要使用“ifeq” (或者“ifneq”)而不是“ifdef”。 可参考前两个小节的内容。
7.2.4 关键字 “ifndef”
关键字“ifndef” 实现的功能和“ifdef” 相反。格式为:
`ifdef VARIABLE-NAME'
这个就不详细讨论了,它的功能就是实现了和 “ifdef” 相反的条件判断。
在“CONDITIONAL-DIRECTIVE” 这一行上,可以以若干个空格开始,make 处理时会被忽略这些空格。但不能以[Tab] 字符做为开始(不然就被认为是命令)。 条件判断语句中,在除关键字( 包括“endif” ) 之前、 条件表达式参数中之外的其他任何地方都可以 使用多个空格或[Tab] 字符,它不会影响条件判断语句的功能。同样 行尾也可以使用注释(“#” 开始直到一行的结束)。 “else” 和“endif” 也是条件判断语句的一部分。在书写时它们都 是没有任何参数的,可以以多个空格开始(同 样不能以[Tab] 字符开始) 多个空格或[Tab] 字符结束。行尾同样可以有注释内容。
在make 读取makefile 文件时计算表达式的值,并根据表达式的值决 定判断语句中那一部分被作为此Makefile 所要执行的内容(选择符合条件的语句)。 因此在条件表达式中不能使用自动化变量,自 动化变量在规则命令执行时才有效。更不能将 一个完整的条件判断语句分写在两个不同的mak efile 文件中,在一个makefile 文件使用指示符“include” 包含另外一个makefile 文件。
7.3 标记测试的条件语句
我们可以使用条件判断语句、 变量“MAKEFLAGS” 和函数“findstring”, 实现对make 命令行选项的测试。看一个例子:
archive.a: ...
ifneq (,$(findstring t,$(MAKEFLAGS)))
+touch archive.a
+ranlib -t archive.a
else
ranlib archive.a
endif
这个条件语句判断make 的命令行参数中是否包含“-t” (用来更新目标文件的时间戳)。 根据命令行参数情况完成对“archive.a” 执行不同的操作。命令行前的“+” 的意思是告诉make, 即使make 使用了“-t” 参数,“+” 之后的命令都需要被执行。
|
|
|