我对cmake很新,并阅读了一些关于如何使用它的教程,并编写了一些复杂的50行CMake脚本,以便为3个不同的编译器制作程序.这可能总结了我在cmake的所有知识.
现在我的问题是我有一些源代码,当我制作程序时,我不想触摸/弄乱它的文件夹.我想要所有cmake并使输出文件和文件夹进入../Compile/,所以我在我的cmake脚本中更改了一些变量,并且它在我的笔记本电脑上做了类似的事情时工作了一段时间:
Compile$ cmake ../src
Compile$ make
Run Code Online (Sandbox Code Playgroud)
在那里,我现在在文件夹中有一个干净的输出,这正是我正在寻找的.
现在我转移到另一台计算机,并重新编译CMake 2.8.11.2,我几乎回到原点!它总是将事物编译到我的CMakeLists.txt所在的src文件夹中.
我在cmake脚本中选择目录的部分是:
set(dir ${CMAKE_CURRENT_SOURCE_DIR}/../Compile/)
set(EXECUTABLE_OUTPUT_PATH ${dir} CACHE PATH "Build directory" FORCE)
set(LIBRARY_OUTPUT_PATH ${dir} CACHE PATH "Build directory" FORCE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${dir})
set(CMAKE_BUILD_FILES_DIRECTORY ${dir})
set(CMAKE_BUILD_DIRECTORY ${dir})
set(CMAKE_BINARY_DIR ${dir})
SET(EXECUTABLE_OUTPUT_PATH ${dir})
SET(LIBRARY_OUTPUT_PATH ${dir}lib)
SET(CMAKE_CACHEFILE_DIR ${dir})
Run Code Online (Sandbox Code Playgroud)
现在它始终以:
-- Build files have been written to: /.../src
Run Code Online (Sandbox Code Playgroud)
我错过了什么吗?
我有一个目前使用C++ 11/14的项目,但它需要类似的东西std::filesystem,它只在C++ 17中可用,因此我没有机会当前使用它.但是,我看到它在我当前的编译器中可用std::experimental::filesystem.使用实验性功能是一个好主意,假设我将来可以添加如下内容:
#ifdef CXX17 //if this is C++17
std::filesystem::something ...;
#else
std::experimental::filesystem::something ...;
#endif
Run Code Online (Sandbox Code Playgroud)
我担心的是:
1.是否保证所有兼容编译器具有相同的实验功能?
2.实验性特征是否容易发生重大变化,使其不可靠?
也许还有更多值得关注的事情.我为什么要或不应该使用它们?我对一个新项目感到困惑,不知道该决定什么.
几个月前,我开始在C中开发用于空间应用的实时系统软件,以及用于C++的微控制器.在这样的系统中有一个经验法则,即永远不应该创建堆对象(因此没有malloc/new),因为它使程序不确定.当人们告诉我时,我无法验证此声明的正确性.那么,这是正确的陈述吗?
对我来说困惑的是,据我所知,确定性意味着两次运行程序将导致完全相同的执行路径.根据我的理解,这是多线程系统的一个问题,因为多次运行相同的程序可能每次都以不同的顺序运行不同的线程.
只是一个帖子来帮助那些尝试这样做的人,因为我没有博客.
这也适用于linux.随意编辑并改进它.
有一个新的实验功能(可能是C++ 20),它是"同步块".该块提供了一段代码的全局锁定.以下是cppreference的示例.
#include <iostream>
#include <vector>
#include <thread>
int f()
{
static int i = 0;
synchronized {
std::cout << i << " -> ";
++i;
std::cout << i << '\n';
return i;
}
}
int main()
{
std::vector<std::thread> v(10);
for(auto& t: v)
t = std::thread([]{ for(int n = 0; n < 10; ++n) f(); });
for(auto& t: v)
t.join();
}
Run Code Online (Sandbox Code Playgroud)
我觉得这是多余的.上面的一个synchronized块和这个之间有什么区别:
std::mutex m;
int f()
{
static int i = 0;
std::lock_guard<std::mutex> lg(m);
std::cout << i << …Run Code Online (Sandbox Code Playgroud) 我有一个很好的内存映射文件示例,用于计算文件的MD5哈希值.这没关系,效果很好.
我想改变它来计算字符串的MD5哈希值.
所以这个例子是:
(包括#include <openssl/md5.h>运行此代码,如果你想运行带有文件的代码,还可以增加内容)
unsigned char result[MD5_DIGEST_LENGTH];
boost::iostreams::mapped_file_source src(path);
MD5((unsigned char*)src.data(), src.size(), result);
std::ostringstream sout;
sout<<std::hex<<std::setfill('0');
for(long long c: result)
{
sout<<std::setw(2)<<(long long)c;
}
return sout.str();
Run Code Online (Sandbox Code Playgroud)
我做的改变是:
std::string str("Hello");
unsigned char result[MD5_DIGEST_LENGTH];
MD5((unsigned char*)str.c_str(), str.size(), result);
std::ostringstream sout;
sout<<std::hex<<std::setfill('0');
for(long long c: result)
{
sout<<std::setw(2)<<(long long)c;
}
return sout.str();
Run Code Online (Sandbox Code Playgroud)
但这会产生结果:
8b1a9953c4611296a827abf8c47804d7
Run Code Online (Sandbox Code Playgroud)
虽然命令$ md5sum <<< Hello给出了结果:
09f7e02f1290be211da707a266f153b3
Run Code Online (Sandbox Code Playgroud)
为什么结果不一致?哪一个错了?
谢谢.
编辑:
所以我得到了正确的答案,在那里打勾.md5sum从终端呼叫的正确方法是:
$ printf '%s' "Hello" | md5sum
Run Code Online (Sandbox Code Playgroud)
避免包含新行.
我一直听到这句话,但我无法真正找到const_cast是邪恶的原因.
在以下示例中:
template <typename T>
void OscillatorToFieldTransformer<T>::setOscillator(const SysOscillatorBase<T> &src)
{
oscillatorSrc = const_cast<SysOscillatorBase<T>*>(&src);
}
Run Code Online (Sandbox Code Playgroud)
我正在使用引用,并使用const,我保护我的引用不被更改.另一方面,如果我不使用const_cast,代码将无法编译.为什么const_cast在这里不好?
这同样适用于以下示例:
template <typename T>
void SysSystemBase<T>::addOscillator(const SysOscillatorBase<T> &src)
{
bool alreadyThere = 0;
for(unsigned long i = 0; i < oscillators.size(); i++)
{
if(&src == oscillators[i])
{
alreadyThere = 1;
break;
}
}
if(!alreadyThere)
{
oscillators.push_back(const_cast<SysOscillatorBase<T>*>(&src));
}
}
Run Code Online (Sandbox Code Playgroud)
请给我一些例子,我可以看到使用const_cast是一个坏主意/不专业.
谢谢你的任何努力:)
我知道 lambda闭包类型没有默认的构造函数。但这是否意味着在将其作为模板参数传递之后无法实例化它?
考虑下面的最小示例:
#include <iostream>
template <typename FuncType>
std::pair<int,int> DoSomething() {
return FuncType()(std::make_pair(1,1));
}
int main() {
auto myLambda = [](std::pair<int,int> x) {
return std::make_pair(x.first*2,x.second*2);
};
std::pair<int,int> res = DoSomething<decltype(myLambda)>();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
由于性能原因,我不能std::function避免使用虚拟指针调用。有没有办法做到这一点?我需要实例化该lambda一次,并在该函数中多次使用它。
当将标准库decltype(myLambda)传递给std::maptemplate参数中的比较器之类的东西时,标准库如何使其工作?
我常常需要一个简单的RAII包装器,但我不想为此创建一个全新的类,原因很多,包括时间限制和组织问题.我的快速解决方案如下.
假设我想确保在范围结束时,我想要一个布尔值切换回其原始状态:
bool prevState = currState;
currState = newState;
std::unique_ptr<int, std::function<void(int*)>> txEnder(new int(0), [&prevState](int* p) {
currState = prevState;
delete p;
});
Run Code Online (Sandbox Code Playgroud)
这个解决方案工作正常,但脏部分是必须分配和释放该整数只是为了使unique_ptr工作和破坏时调用自定义析构函数.
有没有一个更清洁的方法来做这个,而不必写一个完整的类,并摆脱new假人int?
我正在做一个我没有开始的大项目.我的任务是为已有的功能添加一些额外的功能.我处于一种必须使用虚拟继承的情况,因为我有一个钻石模型.情况如下图所示:
Base class
/ \
/ \
My new class A class that was there before (OldClass)
\ /
\ /
\ /
\ /
My other new class
Run Code Online (Sandbox Code Playgroud)
为了实现这一点,中间的两个类都必须从基础继承,public virtual而不是仅仅public.所以:
class OldClass: public BaseClass {}
Run Code Online (Sandbox Code Playgroud)
必须成为:
class OldClass: public virtual BaseClass {}
Run Code Online (Sandbox Code Playgroud)
由于这个项目非常庞大,我正在研究它的一小部分,我不想通过这样做来打破它.我的adhoc测试工作,程序似乎工作正常,但我仍然怀疑.
所以我的问题是:通过添加virtual关键字,我应该期待哪些副作用和后果?有什么值得担心的吗?