标签: template-meta-programming

C ++检查语句是否可以评估为constexpr

有没有一种方法可以确定是否可以对constexpr求值,并将结果用作constexpr布尔值?我的简化用例如下:

template <typename base>
class derived
{
    template<size_t size>
    void do_stuff() { (...) }

    void do_stuff(size_t size) { (...) }
public:
    void execute()
    {
        if constexpr(is_constexpr(base::get_data())
        {
            do_stuff<base::get_data()>();
        }
        else
        {
            do_stuff(base::get_data());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的目标是C ++ 2a。

我发现了以下reddit线程,但我不是宏的忠实拥护者。https://www.reddit.com/r/cpp/comments/7c208c/is_constexpr_a_macro_that_check_if_an_expression/

c++ template-meta-programming constexpr c++20 if-constexpr

23
推荐指数
3
解决办法
1291
查看次数

TMP:如何推广笛卡尔积矢量?

有一个很好的C++解决方案(实际上是2个解决方案:递归和非递归),是一个整数向量向量笛卡尔积.出于说明/简单的目的,让我们只关注非递归版本.

我的问题是,如何用模板推广这个代码来获取std::tuple看起来像这样的同类向量:

{{2,5,9},{"foo","bar"}}

并生成一个齐次的矢量 tuple

{{2,"foo"},{2,"bar"},{5,"foo"},{5,"bar"},{9,"foo"},{9,"bar"}}

如果它让生活更容易,让我们假设输入中的内部向量都是同质的.所以不允许这样的输入: {{5,"baz"}{'c',-2}}

编辑将输入从锯齿状矢量更改为元组

c++ algorithm data-structures template-meta-programming c++11

22
推荐指数
1
解决办法
2731
查看次数

使用比较器网络快速排序固定长度阵列

我有一些性能关键代码,涉及在C++中对大约3到10个元素之间的非常短的固定长度数组进行排序(参数在编译时更改).

在我看来,专门针对每个可能的输入大小的静态排序网络可能是一种非常有效的方法:我们进行必要的比较以确定我们所处的情况,然后进行最佳的交换数量以进行排序数组.

要应用此功能,我们使用一些模板魔法来推断数组长度并应用正确的网络:

#include <iostream>
using namespace std;

template< int K >
void static_sort(const double(&array)[K])
{
    cout << "General static sort\n" << endl;
}

template<>
void static_sort<3>(const double(&array)[3])
{
    cout << "Static sort for K=3" << endl;
}


int main()
{

    double  array[3];

    // performance critical code.
    // ...
    static_sort(array);
    // ...

}
Run Code Online (Sandbox Code Playgroud)

显然,编写所有这些代码非常麻烦,所以:

  • 有没有人对是否值得努力有任何意见?
  • 有谁知道这种优化是否存在于任何标准实现中,例如std :: sort?
  • 是否有一个容易实现这种排序网络的代码?
  • 也许有可能使用模板魔法静态生成这样的排序网络.

现在我只使用带有静态模板参数的插入排序(如上所述),希望它会鼓励展开和其他编译时优化.

欢迎你的想法.


更新: 我写了一些测试代码来比较'static'插入short和std :: sort.(当我说静态时,我的意思是数组大小是固定的并在编译时推断出来(可能是允许循环展开等).我至少得到20%的NET改进(请注意,生成包含在时间中).平台: clang,OS X 10.9.

代码在这里https://github.com/rosshemsley/static_sorting如果你想将它与你的stdlib实现进行比较.

我还没有为比较器网络分拣机找到一套很好的实现.


c++ arrays sorting template-meta-programming sorting-network

22
推荐指数
4
解决办法
3757
查看次数

如何使C++ ADL查看模板的所有实例?

我正在关注如何在C++教程中实现一个常量表达式计数器我正在尝试修复C++ 14没有宏的反射,标记或外部工具..谈话限制.

本教程的基本思想是:

template<int N>
struct flag {
  friend constexpr int adl_flag (flag<N>);
};

template<int N>
struct writer {
   friend constexpr int adl_flag (flag<N>) { return N; }
   static constexpr int value = N;
};

template<int N, class = char[noexcept(adl_flag(flag<N> ()))?+1:-1]>
int constexpr reader (int, flag<N>) { return N; }

template<int N>
int constexpr reader (float, flag<N>, int R = reader (0, flag<N-1>())) { return R; }

int constexpr reader (float, flag<0>) { return …
Run Code Online (Sandbox Code Playgroud)

c++ template-meta-programming constexpr c++11 c++14

22
推荐指数
1
解决办法
728
查看次数

分析模板元程序编译时间

我正在开发一个具有大量编译时计算的C++项目.漫长的编译时间正在减慢我们的速度.我怎样才能找到模板元程序中最慢的部分,以便我可以优化它们?(当我们有慢运行时计算时,我有很多分析器可供选择,例如valgrind的callgrind工具.所以我尝试构建一个调试GCC并分析它编译我们的代码,但我没有从中学到太多东西.)

我使用GCC和Clang,但欢迎任何建议.

profile_templates在Boost的网站上找到了,但似乎记录很少,需要jam/bjam构建系统.如果您展示如何在非卡纸项目1上使用它,我会向您投票.https://svn.boost.org/svn/boost/sandbox/tools/profile_templates/似乎计算实例数,而计算所花费的时间将是理想的.

1 我们的项目使用CMake并且足够小,只需将模板分析用于模板分析就可以接受.

c++ profiling instantiation template-meta-programming

21
推荐指数
2
解决办法
2477
查看次数

奇怪的是相互重复的类定义

我希望两个类中的类型声明相互依赖.这是第一个用clang和gcc编译的例子:

template <class Sum>
struct A
{
    using X = char;                // (1)
    using Z = typename Sum::B::Y;  // (2)
};

template <class Sum>
struct B
{
    using Y = typename Sum::A::X;
};

struct AplusB
{
    using A = ::A<AplusB>;
    using B = ::B<AplusB>;
};

AplusB::A::Z z;

int main() {}
Run Code Online (Sandbox Code Playgroud)

然而,有一个有趣的时刻.如果你交换行(1)和(2),那么它将无法编译并出现错误:

错误:'A'中没有名为'X'的类型

这让我怀疑原始代码在C++标准意义上是否真的有效,或者它恰好编译?

这是第二个例子,它也利用了模板实例化的顺序:

template <class Sum>
struct A
{
    using X = char;
    using P = typename Sum::B::Q;
};

template <class Sum>
struct B
{
    using Y = typename …
Run Code Online (Sandbox Code Playgroud)

c++ templates language-lawyer template-meta-programming

21
推荐指数
1
解决办法
574
查看次数

如何阻止 Clang 通过模板过度扩展嵌套循环?

考虑这段代码:

#include <iostream>
typedef long xint;
template<int N>
struct foz {
    template<int i=0>
    static void foo(xint t) {
        for (int j=0; j<10; ++j) {
            foo<i+1> (t+j);
        }
    }
    template<>
    static void foo<N>(xint t) {
        std::cout << t;
    }

};

int main() {
    foz<8>::foo<0>(0);
}
Run Code Online (Sandbox Code Playgroud)

在编译时clang++ -O0,它会在几秒钟内编译然后运行 ​​4 秒。

然而,使用clang++ -O2,编译需要很长的时间和大量的内存。在Compiler Explorer上可以看到,更改8为较小的值后,它完全展开了循环。

我并不是让它完全没有优化,而是让它不递归,就像嵌套循环应该表现的那样。有什么我应该做的吗?

c++ clang compiler-optimization template-meta-programming loop-unrolling

21
推荐指数
1
解决办法
1320
查看次数

确保模板参数是枚举类

有没有办法确保模板参数是枚举类型?

我知道type_traitsstd::is_enum,但我不希望它匹配常规枚举,只是enum_classes.

想要效果的示例:

enum class EnumClass {};
enum Enum {};
class Class {};

template <typename T>
void Example()
{
    static_assert(/* T is EnumClass */, "`T` must be an enum class");
}

Example<EnumClass>(); // Ok
Example<Enum>(); // Error
Example<Class>(); // Error
Run Code Online (Sandbox Code Playgroud)

我使用的是C++ 11,不幸的是不能再高了(虽然我很想知道解决方案,即使它涉及更新的标准).

可能吗?

c++ template-meta-programming c++11

20
推荐指数
1
解决办法
1759
查看次数

Russell在C++模板中的悖论

考虑这个程序:

#include <iostream>
#include <type_traits>

using namespace std;

struct russell {
    template <typename barber, 
              typename = typename enable_if<!is_convertible<barber, russell>::value>::type>
    russell(barber) {}
};

russell verify1() { return 42L; }
russell verify2() { return 42; }

int main ()
{
    verify1();
    verify2();
    cout << is_convertible<long, russell>::value;
    cout << is_convertible<int, russell>::value;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果某些类型barber无法转换为russell.我们试图通过使其可转换(启用转换构造函数)来创建一个悖论.

输出00有三个流行的编译器,虽然构造函数显然在工作.

我怀疑行为应该是未定义的,但在标准中找不到任何内容.

该计划的输出应该是什么,为什么?

c++ language-lawyer template-meta-programming

20
推荐指数
1
解决办法
508
查看次数

编译时浮点初始化的替代方法

我目前正致力于基于模板元编程的浮点运算实现.表示编译时浮点值的模板如下:

template<bool S , std::int16_t E , std::uint64_t M>
struct number{};
Run Code Online (Sandbox Code Playgroud)

由于使用硬编码的尾数,指数等初始化这些值是一个麻烦且容易出错的过程,我编写了一个模板,用于将十进制值转换为浮点值:

template<std::int64_t INT , std::uint64_t DECS>
struct decimal{};
Run Code Online (Sandbox Code Playgroud)

其中第一个参数表示积分部分,第二个参数表示小数位数.我认为这是一种常见且众所周知的方式.
然而,这种模式会遇到一些问题(如何输入负数小于一的数字?),其中最令我讨厌的事实之一就是没有办法在逗号之后输入零数字,即数字之类的0.00032.

我是C++ 11意识到的,我正在思考一个用户定义的文字+ decltype()方法(即使有一个宏#define FLOAT(x) decltype(x_MY_LITERAL)),但我不确定这种方法在所有情境中是否可行,我的意思是,如果文字+ decltype可在模板参数的上下文中进行评估.

即使这可行,我想知道是否有其他可能的方法来解决这个问题.那么,在编译时通过tmp进行浮点式初始化有哪些替代方案呢?


尝试替代方案:

仅仅为了完整性,我将描述我已经实施的替代方案,它们如何工作,以及它的功能和优点.问题本身仍然是开放的,允许任何人添加更多的替代品.

一些背景

首先,我将描述我使用过的功能,以确保每个人都能理解代码.

我的图书馆,Turbo Metaprogramming Library,基于三个原则:

  • 仅键入模板参数:完全通用的混合类型参数,值参数和模板模板参数非常难(几乎不可能),因此此库仅使用类型参数.无论何时需要使用值或模板,库都提供包装器以通过装箱传递这些参数.

  • 统一表达式评估:在编程语言中工作时的首要需求之一是评估表达式并获取其价值的方法.Turbo提供tml::eval元函数,它接受任何类型的表达式并返回(计算)其值.

  • 通过模板专业化定制的通用算法和元函数:每当我可以使用C++ 11模板别名来避免繁琐的typename ::type构造.我的惯例是在嵌套命名空间上定义实现模板(真正完成工作的元函数)impl,并在当前命名空间上定义结果的C++ 11模板别名.由于这些别名直接返回结果,因此它们无法在复杂表达式上进行求值(考虑元函数瞬时add<X,Y>,其中XY是lambda的变量.如果add是结果的别名,则不起作用,因为评估没有意义.如果我们需要表达式(元函数)而不是直接的结果,我的惯例是在func嵌套命名空间上为元函数添加别名.

这里有些例子:

using bits = tml::util::sizeof_bits<int>; //bits is a size_t integral …
Run Code Online (Sandbox Code Playgroud)

c++ floating-point templates template-meta-programming c++11

19
推荐指数
1
解决办法
1218
查看次数