标签: compile-time

确定函数返回类型的最简单方法

给出一个非常简单但冗长的功能,例如:

int foo(int a, int b, int c, int d) {
    return 1;
}

// using ReturnTypeOfFoo = ???
Run Code Online (Sandbox Code Playgroud)

在编译时确定函数返回类型(ReturnTypeOfFoo在本例中int为:) 的最简单,最简洁的方法是什么,而不重复函数的参数类型(仅限名称,因为已知该函数没有任何额外的重载)?

c++ function return-type compile-time c++17

48
推荐指数
3
解决办法
2617
查看次数

在编译时计算函数参数计数

我有一个 C 库(带有 C 头文件),它存在于两个不同的版本中。

其中之一具有如下所示的函数:

int test(char * a, char * b, char * c, bool d, int e);
Run Code Online (Sandbox Code Playgroud)

另一个版本看起来像这样:

int test(char * a, char * b, char * c, bool d)
Run Code Online (Sandbox Code Playgroud)

(为此, e 不是作为函数参数给出的,而是在函数本身中硬编码的)。

库或其头文件没有定义/包含任何检查库版本的方法,所以我不能只使用#ifor#ifdef来检查版本号。

有什么办法可以编写一个可以用这个库的两个版本编译的C程序,这取决于编译程序时安装的是哪个版本?这样,想要编译我的程序的贡献者可以自由使用库的任一版本,并且该工具可以使用任一版本进行编译。

所以,澄清一下,我正在寻找这样的(或类似的):

#if HAS_ARGUMENT_COUNT(test, 5)
    test("a", "b", "c", true, 20);
#elif HAS_ARGUMENT_COUNT(test, 4)
    test("a", "b", "c", true);
#else
    #error "wrong argument count"
#endif
Run Code Online (Sandbox Code Playgroud)

有没有办法在C中做到这一点?我想不出办法。

该库将是 libogc ( https://github.com/devkitPro/libogc ),它if_config在不久前改变了它的定义,我想让我的程序同时使用旧版本和新版本。我在库中找不到任何版本标识符。目前我使用的是 GCC 8.3 的修改版本。

c overloading compile-time

46
推荐指数
5
解决办法
2555
查看次数

如何在C中编译时打印sizeof()的结果?

如何在C中编译时打印sizeof()的结果?

现在我使用静态断言(基于其他Web资源自酿)来将sizeof()结果与各种常量进行比较.虽然这有效但它远非优雅或快速.我还可以创建变量/ struct的实例并查看映射文件,但这比直接调用/命令/运算符更不优雅和快速.此外,这是一个使用多个交叉编译器的嵌入式项目......因此,为目标构建和加载示例程序然后读出一个值比上述任何一个都更麻烦.

在我的情况下(旧的GCC),#warning sizeof(MyStruct)在打印警告之前实际上并没有解释sizeof().

c sizeof compile-time

43
推荐指数
5
解决办法
2万
查看次数

使用std :: map <K,V>其中V没有可用的默认构造函数

我有一个符号表实现为std::map.对于该值,无法通过默认构造函数合法地构造值类型的实例.但是,如果我不提供默认构造函数,我会收到编译器错误,如果我使构造函数断言,我的程序编译得很好,但map<K,V>::operator []如果我尝试使用它来添加新成员,则会崩溃.

有没有办法让C++ map[k]在编译时禁止作为l值(同时允许它作为r值)?


顺便说一句:我知道我可以使用插入地图Map.insert(map<K,V>::value_type(k,v)).


编辑:有几个人提出的解决方案相当于改变值的类型,以便映射可以构造一个而不调用默认构造函数.这与我想要的完全相反,因为它将错误隐藏到以后.如果我愿意这样做,我可以简单地从构造函数中删除断言.我想要的是让错误更快发生; 在编译时.然而,似乎没有办法区分r值和l值使用,operator[]所以看起来我想要的不能这样做,所以我只需要免除一起使用它.

c++ stl map compile-time

42
推荐指数
3
解决办法
1万
查看次数

std::less 是否应该允许在编译时比较不相关的指针?

考虑这个代码:

#include <functional>
#include <typeinfo>

template <typename T>
inline constexpr const void *foo = &typeid(T);

int main()
{
    constexpr bool a = std::less<const void*>{}(foo<int>, foo<float>);
} 
Run Code Online (Sandbox Code Playgroud)

Run on gcc.gotbolt.org

如果我使用<而不是std::less这里,代码不会编译。这并不奇怪,因为如果指针指向不相关的对象,则关系指针比较的结果是未指定的,而且显然这样的比较不能在编译时完成。

#include <functional>
#include <typeinfo>

template <typename T>
inline constexpr const void *foo = &typeid(T);

int main()
{
    constexpr bool a = std::less<const void*>{}(foo<int>, foo<float>);
} 
Run Code Online (Sandbox Code Playgroud)

即使我使用std::less. 编译器错误是一样的。std::less似乎<至少在 libstdc++ 和 libc++ 中实现;我在 GCC、Clang 和 MSVC 上得到了相同的结果。

但是,关于 cppreference 的页面 …

c++ std compile-time language-lawyer

39
推荐指数
2
解决办法
1095
查看次数

如何在编译期间切换/选择类型?

我是否有一种标准方法可以在编译时在c ++ 11中的无符号索引上选择类型?

例如,类似于:

using type_0 = static_switch<0,T,U>;  // yields type T
using type_1 = static_switch<1,T,U>;  // yields type U
Run Code Online (Sandbox Code Playgroud)

如果有一个variadic-template版本,那将非常有用.

c++ templates compile-time type-traits c++11

38
推荐指数
3
解决办法
4910
查看次数

在编译时通过算法初始化std :: array

考虑:

static constexpr unsigned num_points{ 7810 };
std::array< double, num_points > axis;

for (int i = 0; i < num_points; ++i)
{
    axis[i] = 180 + 0.1 * i;
}
Run Code Online (Sandbox Code Playgroud)

axis是全类常量。我想避免像其他任何全局变量一样初始化它。可以在编译时完成吗?


这是完整的最后一堂课:

// https://www.nist.gov/pml/atomic-spectroscopy-compendium-basic-ideas-notation-data-and-formulas/atomic-spectroscopy
// https://www.nist.gov/pml/atomic-spectra-database
struct Spectrum
{
    static constexpr unsigned _num_points{ 7810 };
    using Axis = std::array< double, _num_points >;

    static constexpr Axis _x{ [] ()            // wavelength, nm
        {
            Axis a {};
            for( unsigned i = 0; i < _num_points; ++i )
            {
                a[ i ] …
Run Code Online (Sandbox Code Playgroud)

c++ initialization compile-time stdarray c++17

36
推荐指数
3
解决办法
2420
查看次数

如何使用C++模板减少编译时间

我正在将我的C++应用程序的一部分从使用旧的C类型数组更改为模板化的C++容器类.有关详情,请参阅此问题.虽然解决方案运行良好,但我对模板化代码所做的每一个小改动都会导致进行大量的重新编译,从而大大减慢构建时间.有没有办法从标题中取出模板代码并返回到cpp文件,这样小的实现更改不会导致重大的重建?

c++ templates compile-time

34
推荐指数
5
解决办法
2万
查看次数

从函数传递/返回数组(非指针)引用的一般规则?

我们可以将数组的引用传递给如下函数:

void f(int (&a)[5]);

int x[5];
f(x);     //okay
int y[6];
f(y);     //error - type of y is not `int (&)[5]`.
Run Code Online (Sandbox Code Playgroud)

或者甚至更好,我们可以编写一个函数模板:

template<size_t N>
void f(int (&a)[N]); //N is size of the array!

int x[5];
f(x);     //okay - N becomes 5
int y[6];
f(y);     //okay - N becomes 6
Run Code Online (Sandbox Code Playgroud)

现在我的问题是,如何从函数返回数组的引用?

我想从函数返回以下类型的数组:

int a[N];
int a[M][N];
int (*a)[N];
int (*a)[M][N];
Run Code Online (Sandbox Code Playgroud)

其中,MN在编译时已知!

从函数传递和返回数组的编译时引用的一般规则是什么?我们如何int (*a)[M][N]将函数数组的引用传递给函数?

编辑:

Adam评论说:int (*a)[N]不是数组,它是指向数组的指针.

是.但是在编译时已知一个维度!我们如何将这个在编译时已知的信息传递给函数?

c++ arrays compile-time

33
推荐指数
3
解决办法
3万
查看次数

对于非指针类型,使用static_cast而不是C样式转换是否有任何优势?

我很清楚使用static_cast而不是C样式转换为指针类型的优势.

如果指针类型不兼容,则:

  • static_cast 将在源代码中的特定行产生编译时错误
  • C风格的转换可能会在程序执行中的"随机"点导致运行时错误

但我无法找到非指针类型的任何类似示例.

换句话说,两种转换方法对非指针类型产生相同的结果.

这是正确的,还是我错过了什么?

如果是,仅static_cast用于非指针类型以保持编码一致性?

c++ casting compile-time

33
推荐指数
4
解决办法
3063
查看次数