我有以下头文件:
power.hpp:
#pragma once
#include <type_traits>
template <typename T, typename R = decltype(std::declval<T>() * std::declval<T>())>
constexpr inline R square(const T& x_) noexcept;
power.inl:
#pragma once
#include "power.hpp"
template <typename T, typename R>
constexpr inline R square(const T& x_) noexcept
{
return (x_ * x_);
}
power_unit_test.cpp:
#include <power.inl>
int main()
{
static_assert(square(2) == 4);
assert(square(2) == 4);
square(2);
return (0);
}
在使用clang ++编译标志-fprofile-instr-generate
和-fcoverage-mapping
之后。运行单元测试二进制文件,我得到一个报告,告诉我main中的三行都被调用了,但是函数内容仅被使用了一次。这种用法来自对square(2)
的独立调用,断言似乎无法正确生成覆盖率报告。
如果我删除独立的square(2)
,则覆盖率达不到100%,因为断言由于某种原因错过了覆盖率。
覆盖率报告显示为:
power.inl:
22| | template <typename T, typename R>
23| | constexpr inline R square(const T& x_) noexcept
24| 0| {
25| 0| return (x_ * x_);
26| 0| }
power_unit_test.cpp
29| |int main()
30| 1|{
31| 1| static_assert(arc::math::sq(2) == 4);
32| 1| assert(arc::math::sq(2) == 4);
33| 1| // arc::math::sq(2);
34| 1|
35| 1| return (0);
36| 1|}
请您能帮助我了解为什么未按我期望的那样报告承保范围吗?这是llvm-cov中的错误,还是我不了解保险范围的意图?
使用自制的铛7.0.1在MacOS编译。将CMake 3.13.2用于构建系统。
答案 0 :(得分:1)
您遇到的问题是编译器为两个assert方法都内联了square()
函数。由于代码是内联的,因此它永远不会调用您的外部代码。
您的第一个想法可能是删除inline
标识符,但这不会起作用。这是因为您的编译器很可能足够聪明,可以识别出square()
函数 可以被内联并且可以继续执行它。最终结果是外部代码没有被调用。
因此,您需要一种绕过square()
函数的内联的方法。您可以使用函数指针执行此操作。请参见对main
函数的以下修改:
int main()
{
int (*f_ptr)(const int&); // Ptr to func that takes 'const int&' and returns 'int'
f_ptr = □
static_assert(square(2) == 4); // Cant use 'f_ptr' here
assert(f_ptr(2) == 4);
f_ptr(2);
return (0);
}
在上面的代码中,我们用指向函数square(const int&)
的指针替换了对f_ptr
的显式调用。结果,编译器将不会自动内联断言中的函数,并且代码将被成功调用两次。结果:
power.cpp:
4| |template <typename T, typename R>
5| |constexpr inline R square(const T& x_) noexcept
6| 2|{
7| 2| return (x_ * x_);
8| 2|}
power_unit_test.cpp:
5| |int main()
6| 1|{
7| 1| int (*f_ptr)(const int&);
8| 1| f_ptr = □
9| 1|
10| 1| static_assert(square(2) == 4);
11| 1| assert(f_ptr(2) == 4);
12| 1| f_ptr(2);
13| 1|
14| 1| return (0);
15| 1|}
快速笔记。由于static_assert
本质上是一个编译时断言,因此我们不能用函数指针替换对square()
的调用,因为函数指针不是constant expressions。但是请放心,如果您尝试在此处将square(2)
替换为函数指针f_ptr(2)
,则编译器足够聪明,可以抱怨。