考虑以下简单的 C++ 程序:
// main.cpp
#include <iostream>
int main()
{
std::cout << "Hello World" << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我使用 CMake 为该项目生成 Makefile,然后使用 GNU Make 和 g++ 进行构建。我的CMakeLists.txt
文件看起来像这样(实际上更复杂,这当然是简化的):
cmake_minimum_required(VERSION 3.20)
project(HelloWorld VERSION 1.0 LANGUAGES CXX)
add_executable(HelloWorld main.cpp)
Run Code Online (Sandbox Code Playgroud)
一切正常,但是在构建调试版本时:
cmake -DCMAKE_BUILD_TYPE=Debug ..
Run Code Online (Sandbox Code Playgroud)
我注意到使用的调试器标志是-g
。当运行make VERBOSE=1
查看使用了哪些标志时,编译时会显示以下内容main.cpp
:
[ 50%] Building CXX object CMakeFiles/HelloWorld.dir/main.cpp.o
/usr/bin/c++ -g -MD -MT CMakeFiles/HelloWorld.dir/main.cpp.o -MF CMakeFiles/HelloWorld.dir/main.cpp.o.d -o CMakeFiles/HelloWorld.dir/main.cpp.o -c /home/HelloWorld/main.cpp
Run Code Online (Sandbox Code Playgroud)
请注意-g
CMake 自动放置的用于添加调试信息的标志。
我怎样才能将其更改-ggdb3
为呢?
在我阅读Ken Arnold 撰写的文章程序员是人之后,我一直在尝试在最小的C++ API中实现渐进式公开的概念,以了解如何在更大规模上完成它.
渐进式公开是指将API"拆分"为仅在请求时将向API的用户公开的类别的想法.例如,API可以分为两类:基本类别(默认情况下可供用户访问),通常需要和易于使用的方法,以及专家级服务的扩展类别.
我在Web上只找到了一个这样一个实现的例子:db4o库(用Java 编写),但我真的不了解他们的策略.例如,如果我们看一下ObjectServer,它就被声明为一个接口,就像它的扩展类ExtObjectServer一样.然后定义继承自这两个接口的实现ObjectServerImpl类,并在那里实现来自两个接口的所有方法.
这应该允许代码如下:
public void test() throws IOException {
final String user = "hohohi";
final String password = "hohoho";
ObjectServer server = clientServerFixture().server();
server.grantAccess(user, password);
ObjectContainer con = openClient(user, password);
Assert.isNotNull(con);
con.close();
server.ext().revokeAccess(user); // How does this limit the scope to
// expert level methods only since it
// inherits from ObjectServer?
// ...
});
Run Code Online (Sandbox Code Playgroud)
我对Java的了解并不是那么好,但似乎我误解了这项工作是如何处于更高层次的.
谢谢你的帮助!
想象一下我有以下课程:
class Extra final
{
public:
void Method1() const {std::cout << "Method 1" << std::endl;}
void Method2() const {std::cout << "Method 2" << std::endl;}
};
Run Code Online (Sandbox Code Playgroud)
我为某些类创建了T
一个类模板,该模板可以Extra
根据不同的场景(在枚举中列出)在编译时启用/禁用方法:
enum class Scenario
{
None, // No extra.
One, // Only Method1 allowed.
Two, // Only Method2 allowed.
Both // Both Method1 and Method2 allowed.
};
Run Code Online (Sandbox Code Playgroud)
类模板如下所示:
template<typename T, Scenario R>
class ExtraAdder : public T
{
};
template<typename T>
class ExtraAdder<T, Scenario::One> : public T
{
public:
void Method1Extra() …
Run Code Online (Sandbox Code Playgroud) 考虑以下代码:
#include <cstdint>
class A
{
public:
explicit A(uint8_t p_a){ m_a = p_a; };
uint8_t get_a() const {return m_a;}
private:
uint8_t m_a;
};
int main()
{
A a {0x21U};
A aa{0x55U};
uint8_t mask{a.get_a() | aa.get_a()};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我尝试编译this(gcc 5.4.0
)时,我收到以下错误:
main.cpp: In function ‘int main()’:
main.cpp:20:28: warning: narrowing conversion of ‘(int)(a.A::get_a() | aa.A::get_a())’ from ‘int’ to ‘uint8_t {aka unsigned char}’ inside { } [-Wnarrowing]
uint8_t mask{a.get_a() | aa.get_a()};
Run Code Online (Sandbox Code Playgroud)
我真的不明白为什么会有任何缩小.该int
类型从未在我的代码中的任何地方使用过,所有内容都是用unsigned char
s语言编写的.即使我明确地转向unsigned char
我得到错误:
uint8_t …
Run Code Online (Sandbox Code Playgroud) 似乎很难找到有关 Gtkmm 主题的高质量文档。
Gtkmm 有好的文档吗?如果有的话,我在哪里可以找到它?
我试图std::bind
去一个lambda时遇到了错误.以下代码示例编译正常:
#include <functional>
#include <iostream>
int main()
{
const auto lambda1 = [](int a, int b){ return a + b; };
std::cout << (std::bind( lambda1, std::placeholders::_1, 2))(2)
<< std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但以下不是:
#include <functional>
#include <iostream>
int main()
{
const auto lambda2 { [](int a, int b){ return a + b; } }; // Note the "{ }-initialization"
std::cout << (std::bind( lambda2, std::placeholders::_1, 2))(2)
<< std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是我使用Visual Studio 2013得到的错误输出,更新4:
1>------ Build started: Project: Project1, …
Run Code Online (Sandbox Code Playgroud) 我正在使用 Doxygen 来记录一个越来越大的 C++ 项目,我一直想知道如何使 Doxygen 成为该项目的构建要求。换句话说,如果有任何类/方法/等,我希望我的构建过程失败并停止。Doxygen尚未成功记录。我用于make
建筑。
例如,我希望它失败(即不构建):
/**
* @bbrief Oops, tag does not exist, warning is issued and hence build fails.
*/
void f()
{
// Do something...
}
/**
* @brief Main function for program X
*
* @return End of execution status.
*
* ...
*
*/
int main()
{
f();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但这要构建:
/**
* @brief Okay, this is fine.
*
*/
void f()
{
// Do something...
}
/** …
Run Code Online (Sandbox Code Playgroud) 我正在使用TYPED_TEST
google测试功能编写测试,这使我可以将测试推广到多种类型.我正在测试类型int
和类的类模板double
.在测试中,我需要生成随机数.为此,我尝试使用std::uniform_int_distribution<T>
和std::uniform_real_distribution<T>
但是遇到了静态断言.
如名称所示,std::uniform_int_distribution<T>
检查if T
是否为整数类型并std::uniform_real_distribution<T>
检查T
是否为浮点类型.
由于我的测试自动测试int
然后测试double
,我一直在尝试编写某种函数,这将允许我在编译时为类型选择正确的类型.更确切地说,类似于:
template<class T>
Distribution get_right_distribution(const T& a, const T& b)
{
if(T is integral) // Compile time is needed, runtime
// fails since both if and else have to compile
{
return std::uniform_real_distribution(a, b);
}
else
{
return std::uniform_real_distribution(a, b);
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,这只是我试图做的伪代码.这种逻辑分支失败,因为if
AND else
必须编译.
我已经做了一些研究如何做到这一点,我觉得std::is_integral<T>
并且std::is_floating_point<T>
是解决方案的一部分,但到目前为止我还没有能够编译任何东西.我主要尝试了两件事:
enable_if
. …这将清洁整个表面:
void surface_clean(Mpaint *mpaint)
{
mpaint->surface=cairo_image_surface_create_from_png("cxl.cache.png");
}
Run Code Online (Sandbox Code Playgroud)
我只想以、、和cairo_surface_t
方式清洁该区域。x
y
width
height
有没有这方面的接口?
我一直在研究一些 makefile,它们调用一些 python 脚本来执行各种任务。到目前为止,我一直在make
安装了 Ubuntu 16.04(64 位)的机器上运行。今天,我尝试使用相同的 makefile 在我的旧 32 位机器上使用 Lubuntu 16.04 进行构建,但在调用 Python 脚本时失败。
起初,我以为我的Python版本不够新,但我也安装了Python 3.5,并且我将python3
makefile中的行更改为,但仍然失败:
python3 /home/morane/Documents/Programming/ConnectX/cxPythonTools/RunUnitTests.py -t /home/morane/bin/tests/unit/cxUnitTests.out -l /home/morane/bin/tests/unit/log/unitTests.log
Traceback (most recent call last):
File "/home/morane/RunUnitTests.py", line 41, in <module>
from subprocess import CREATE_NEW_CONSOLE
ImportError: cannot import name 'CREATE_NEW_CONSOLE'
Makefile:51: recipe for target 'unittests' failed
make: *** [cxbaseunit] Error
Run Code Online (Sandbox Code Playgroud)
为了测试,我尝试直接在 Python shell 中重复该错误:
Python 3.5.2+ (default, Sep 22 2016, 12:18:14)
[GCC 6.2.0 20160927] on linux
Type "help", "copyright", "credits" or "license" …
Run Code Online (Sandbox Code Playgroud) 在2017年的cppcon视频中,我遇到了Klaus Iglberger的一个名为" Free Your Functions! " 的演讲.在这次演讲中,演讲者谈到了如何切换到自由函数可以简化测试私有方法的过程(参见19:00).这个想法是你将私有方法拉出类(你使它成为一个自由函数),它变得可测试.
起初,我觉得这个想法很有意思,但是我想的越多,我就越不了解这实际上应该如何工作.例如,假设我有以下(虚拟)类:
class SomeClass
{
public:
SomeClass();
~SomeClass();
void someTask();
private:
void someComplexTask();
void someOtherComplexTask();
};
void SomeClass::someTask()
{
someComplexTask();
someOtherComplexTask();
}
// private tasks implementations...
Run Code Online (Sandbox Code Playgroud)
然后someComplexTask()
和someOtherComplexTask()
是私有方法.这意味着它们是实现细节,即它们只能在内部SomeClass
(或朋友)调用.在我看来,如果你让它们成为自由函数,是的它们变得可测试,但它们不再是私有的,也不仅仅是特定的实现细节SomeClass
.实际上,它们可以从代码中的任何地方调用......
所以我的问题是:为什么Iglberger先生的观点有效?
我们正在对 React-Native 应用程序(使用 Jest)进行单元测试,该应用程序使用fetch
.
fetch
为了测试它们,我们模拟了 API 调用函数中的调用。到目前为止效果很好。我们还有组合这些 API 调用并对其进行一些逻辑操作的函数。
例如,下面是一个函数,给定令牌后,该函数将获取相关用户的第一个项目 ( project[0]
) 并返回该项目中的项目列表。
export async function getAllItems(token) {\n try {\n const response = await getCurrentUser(token); // fetch called inside\n const responseJson = await response.json();\n const allItemsResp = await getAllItemsFromSpecificProject(\n token,\n responseJson.projectIds[0],\n ); // fetch called inside\n return await allItemsResp.json();\n } catch (error) {\n console.log(error);\n return null;\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n函数getCurrentUser
和getAllItemsFromSpecificProject
都是简单的fetch
调用,目前已正确模拟。这是一个尝试测试该getAllItems
功能的测试:
it('Gets all items', async () …
Run Code Online (Sandbox Code Playgroud)