我正在开发一个C++库.最后,我想公开提供多个平台(至少Linux和Windows),以及一些示例和Python绑定.工作进展顺利,但目前该项目非常混乱,仅针对Visual C++构建,而不是多平台构建.
因此,我觉得清理是有序的.我想改进的第一件事是项目的目录结构.我想创建一个适合Automake工具的结构,以便在多个平台上轻松编译,但我以前从未使用过这些.由于我仍然会在Visual Studio中进行(大部分)编码,因此我需要在某处保留我的Visual Studio项目和解决方案文件.
我试图像谷歌"C++库目录结构"这样的术语,但似乎没有任何用处.我找到了一些非常基本的指导方针,但没有明确的解决方案
在查看一些开源库时,我想出了以下内容:
\mylib
\mylib <source files, read somewhere to avoid 'src' directory>
\include? or just mix .cpp and .h
\bin <compiled examples, where to put the sources?>
\python <Python bindings stuff>
\lib <compiled library>
\projects <VC++ project files, .sln goes in project root?>
\include?
README
AUTHORS
...
Run Code Online (Sandbox Code Playgroud)
我以前没有/很少有多平台开发/开源项目的经验,我很惊讶我找不到关于如何构建这样一个项目的任何好的指导.
人们应该如何构建这样的图书馆项目?建议阅读什么?有一些很好的例子吗?
我需要执行一个程序并在c ++中检索它的stdout输出.我希望我的代码也是跨平台的.
最近我发现了针对您所有跨平台需求的Boost c ++库的精彩世界,我想我会去boost.org并阅读Boost.Process的文档.令我惊讶的是,它不存在!然后我开始弄清楚Boost给他们的跨平台库启动外部进程的名称,但到目前为止还没有找到它.
谷歌搜索带我去了Julio M. Merino Vidal的Boost.Process,它似乎是我正在寻找的非官方Boost库.奇怪的是,我似乎无法在该网站上找到下载链接.似乎该项目最近没有任何进展.
我终于能够在外部网站上找到Vidal的Boost.Process的下载链接,并且现在将使用它,但是我非常惊讶于我需要付出的努力才能获得跨平台的c ++库.与外部流程互动.
那么,为什么没有正式的Boost.Process?这似乎是一个非常有价值的补充.或者我完全忽视了这里明显的解决方案?您是否可以建议其他跨平台库来管理外部流程的简单启动和交互?
我正在设计一个数据库,用于存储源自许多不同来源的数据.我存储的实例由原始源分配唯一ID.我存储的每个实例都应包含有关其来源的信息,以及该源关联的ID.
例如,请考虑下表说明问题:
----------------------------------------------------------------
| source_id | id_on_source | data |
----------------------------------------------------------------
| 1 | 17600 | ... |
| 1 | 17601 | ... |
| 2 | 1 | ... |
| 3 | 1 | ... |
----------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
请注意,虽然id_on_source
每个源都是唯一的,但可以id_on_source
为不同的源找到相同的源.
我对关系数据库有一个很好的理解,但远非专家甚至是有经验的用户.我在设计中遇到的问题是我应该用作主键的问题.数据似乎决定使用复合主键(source_id, id_on_source)
.经过一番谷歌搜索后,我发现了一些关于复合主键优缺点的激烈争论,让我有点困惑.
该表与其他表具有一对多的关系,因此将在其他表的外键中引用.
我不依赖于特定的RDBMS
,我不知道这是否事项的参数的缘故,但让我们说,我更喜欢的工作SQLite
和MySQL
.
在这种情况下使用复合外键有哪些优缺点?你更喜欢哪个?
请考虑以下示例:
struct Scanner
{
template <typename T>
T get();
};
template <>
string Scanner::get()
{
return string("string");
}
template <>
int Scanner::get()
{
return 10;
}
int main()
{
Scanner scanner;
string s = scanner.get<string>();
int i = scanner.get<int>();
}
Run Code Online (Sandbox Code Playgroud)
所述Scanner
类被用来提取从一些源令牌.上面的代码工作正常,但是当我尝试get
其他整数类型如a char
或an 时失败unsigned int
.读取这些类型的代码与要读取的代码完全相同int
.我可以复制我想要阅读的所有其他整数类型的代码,但我宁愿为所有整数类型定义一个函数模板.
我尝试过以下方法:
struct Scanner
{
template <typename T>
typename enable_if<boost::is_integral<T>, T>::type get();
};
Run Code Online (Sandbox Code Playgroud)
这有点像魅力,但我不确定如何Scanner::get<string>()
再次运作.所以,我怎么能写代码,这样我可以做scanner.get<string>()
和scanner.get<any integral type>()
,有一个统一的定义读取所有整数类型?
更新:奖金问题:如果我想根据某些特征接受多个课程范围怎么办?例如:如果我想要有三个get
函数分别接受(i)整数类型(ii)浮点类型(iii)字符串,我应该如何处理这个问题 .
我试图将Boost.Log集成到一个相当大的应用程序中,该应用程序由一个动态加载DLL插件的主应用程序组成.最初的想法是将日志源传递给插件,以便他们可以添加日志消息.但是,只要DLL中的代码尝试将消息记录到提供的源,应用程序就会因访问冲突而崩溃.
以下最小示例说明了此问题:
int main(int argc, char* argv[])
{
boost::log::sources::severity_logger_mt<boost::log::trivial::severity_level> logger;
// This is okay
BOOST_LOG_SEV(logger, boost::log::trivial::info) << "From main()";
// This crashes
logFromDll(logger);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在logFromDll
单独的(DLL)项目中定义的位置:
Dll.cpp
TESTDLL_API void logFromDll(boost::log::sources::severity_logger_mt<boost::log::trivial::severity_level> &logger)
{
BOOST_LOG_SEV(logger, boost::log::trivial::info) << "From dll";
}
Run Code Online (Sandbox Code Playgroud)
如上所述,这会在访问冲突中崩溃logFromDll
(使用visual studio 2010编译).
Boost.Log为日志源的"全局存储"提供了一种机制:
声明了全局记录器后,可以确保从应用程序代码的任何位置对此记录器实例进行线程安全访问.该库还保证全局记录器实例即使跨模块边界也是唯一的.
听起来和我需要的完全一样.所以我设置了以下示例:
Logger.h
BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(my_logger, boost::log::sources::severity_logger_mt<boost::log::trivial::severity_level>)
Run Code Online (Sandbox Code Playgroud)
Main.cpp的
int main(int argc, char* argv[])
{
boost::log::add_console_log
(
std::clog,
boost::log::keywords::format =
(
boost::log::expressions::stream << "[Custom format] " << boost::log::expressions::smessage …
Run Code Online (Sandbox Code Playgroud) 我正在使用typedef来定义程序中容器的类型,这样我就可以在使用普通STL容器和STXXL容器之间轻松切换,顺序如下:
typedef stxxl:vector<Data> MyContainer;
Run Code Online (Sandbox Code Playgroud)
要么
typedef std:vector<Data> MyContainer;
Run Code Online (Sandbox Code Playgroud)
一个难点是STXXL提供了一个特殊版本std::for_each
,stxxl::for_each
它针对STXXL容器进行了优化.当MyContainer的typedeffed为a时,我更喜欢使用此函数stxxl::vector
.
一种解决方案是定义我自己的for_each
函数,该for_each
函数调用正确的函数并在我想要调用时使用它for_each
.
我正在研究的另一个解决方案是重载/特化,std::foreach
以便stxxl::for_each
在使用stxxl::vector<Data>::(const_)iterator
第一个和第二个参数调用它时调用它.
我不能让第二个想法工作.我尝试过以下方法:
namespace std
{
template <class UnaryFunction>
UnaryFunction for_each(stxxl:vector<Data>::const_iterator first,
stxxl:vector<Data>::const_iterator last, UnaryFunction f)
{
stxxl::for_each(first, last, f, 4);
}
}
Run Code Online (Sandbox Code Playgroud)
与非const迭代器的类似函数一起使用.虽然他们没有被召唤.
这个问题的首选解决方案是什么?我怎样才能让我的版本std::for_each
为stxxl::vector
得到所谓的迭代器?
更新:我发布了第二个想法.问题是我包含了错误的文件(哎呀......).但问题仍然存在:这个问题的首选解决方案是什么?是否可以重载std :: for_each,因为std命名空间不适合凡人?
我正在为我正在学习的c ++课程开发一个静态库项目.老师坚持认为我们只为每个源文件定义一个函数,将属于同一类的文件/函数分组到每个类的子目录中.这导致了如下结构:
MyClass
\MyClass.cc (constructor)
\functionForMyClass.cc
\anotherFunctionForMyClass.cc
OtherClass
\OtherClass.cc (constructor)
Run Code Online (Sandbox Code Playgroud)
这是不是好的做法是我不想讨论的事情,因为我只是以这种方式组织我的项目.
我正在使用visual studio 2008,并且在两个类中使用同名函数(以及文件名)时会出现奇怪的链接错误.这似乎是由于visual studio将所有.obj
文件(每个源文件一个)放在一个中间目录中,在编译具有相同名称的源文件时覆盖先前生成的目标文件.
这可以通过根据输入文件的相对路径将目标文件放在子目录中来解决.Visual Studio允许用户配置它生成的目标文件的名称,并在那里使用宏,但似乎没有"输入文件的相对路径"的宏.
那么,有没有办法让这个工作?如果没有,为每个班级使用一个项目最好的解决方案?
我需要在c ++中存储一组int和double(表示名义和实数值).我显然可以将它们全部存储在一起std::vector<double>
,但这感觉有点不对,并没有获得美学奖励积分.
我也可以基于多态来烹饪一些东西,但我也需要集合非常有效:存储和检索集合中的数据应该尽可能快.我发现很难判断这样的解决方案是否最有效.
我还发现了boost :: variant,这可能会有所帮助.
附加信息:集合中的项目数量很少(<100),并在初始化集合时已知.
总结:我显然可以通过无数种方式解决这个问题,但我不确定在(i)效率非常重要和(ii)我还想编写一些不错的代码时,什么是一个好的解决方案.我最好的选择是什么?
编辑,附加信息:集合表示较大数据集中的"行",其元素表示某些"列"的值.行的属性是已知的,因此知道在哪个位置存储什么类型的数据.我所讨论的'效率'主要是检索某列的int/double值的效率,尽管快速设置值也很重要.我有一些函数可以对需要尽快检索的数据进行操作.例:
typedef std::vector<double> Row;
void doubleFun(Row const &row)
{
// Function knows there's always a double at index 0
double value = row[0];
...
}
void integerFun(Row const &row)
{
// Function knows there's always an integer at index 1
int value = row[1];
...
}
Run Code Online (Sandbox Code Playgroud)
经过一番思考和阅读建议到目前为止,似乎只是将int列和双列存储在两个单独的向量中是一个可靠的解决方案.Row
然后,该集合可以定义两个不同的成员,用于检索函数可以使用的名义和实际数据.
vector<double>
我想,只是存储为一个没问题,但这取决于double和int之间的转换速度有多快(这可能相当令人印象深刻).
抱歉一开始有点不清楚,我希望现在更清楚了,我可以对此事有更多的想法.
我有一个相当大的解决方案偶尔会崩溃.遗憾的是,这些崩溃似乎只发生在发布版本中.当我在崩溃时附加调试器时,我收到消息:
"没有为任何调用堆栈帧加载符号.源代码无法显示"
这使得很难找到崩溃的原因.我正在使用visual studio 2008的默认版本构建设置,其中"调试信息格式"设置为"程序数据库(/ Zi)".
你有什么提示可以帮我找到这个bug吗?例如,我可以更改项目中的某些设置,以便崩溃可能仍然发生但在调试器中获取更有意义的信息吗?
更新:问题是一个非常罕见的逻辑错误,本身不应该导致崩溃,但显然导致其他地方崩溃.解决逻辑错误解决了崩溃行为.
对于那些来到这里寻找解决类似问题的人来说:运气好的话,你是一个艰难的旅程.最终帮助我找到问题的是在代码中添加了大量的边界检查(我可以使用预处理器指令启用/禁用)并为linux编译并使用gdb/valgrind运行.