相关疑难解决方法(0)

编译时常量id

鉴于以下内容:

template<typename T>
class A
{
public:
    static const unsigned int ID = ?;
};
Run Code Online (Sandbox Code Playgroud)

我希望ID为每个T生成一个唯一的编译时间ID.我考虑过__COUNTER__并且增强PP库但到目前为止都没有成功.我怎样才能做到这一点?

编辑:ID必须可用作switch语句中的大小写

Edit2:基于静态方法或成员地址的所有答案都不正确.尽管它们确实创建了唯一的ID,但它们在编译时未得到解析,因此不能用作switch语句的情况.

c++ templates template-meta-programming

43
推荐指数
4
解决办法
8410
查看次数

C++ 编译时间计数器,重温

TL; 博士

在您尝试阅读整篇文章之前,请了解:

  1. 我自己已经找到了解决所提出问题的方法,但我仍然很想知道分析是否正确;
  2. 我已将解决方案打包到一个fameta::counter类中,以解决一些剩余的怪癖。你可以在 github 上找到它
  3. 你可以在 Godbolt 上看到它。

一切是如何开始的

自从 Filip Roséen 在 2015 年发现/发明了通过友元注入编译时间计数器的黑魔法是在 C++ 中,我一直对这个设备有点着迷,所以当 CWG决定功能必须去时,我很失望,但仍然充满希望可以通过向他们展示一些引人注目的用例来改变他们的想法。

然后,几年前,我决定再看一遍,以便uberswitch es可以嵌套 - 在我看来,这是一个有趣的用例 - 只是发现它不再适用于新版本的可用的编译器,即使问题 2118是(现在仍然是)处于打开状态:代码会编译,但计数器不会增加。

该问题已在 Roséen 的网站和最近的 stackoverflow 上报告:Does C++ support compile-time counters?

几天前,我决定再次尝试解决这些问题

我想了解编译器发生了什么变化,使看似仍然有效的 C++ 不再起作用。为此,我在互联网上广泛搜索,寻找有人谈论它,但无济于事。所以我开始尝试并得出了一些结论,我在这里提出这些结论是希望能从这里的知识渊博的人那里得到反馈。

为了清楚起见,我在下面展示了 Roséen 的原始代码。有关其工作原理的说明,请参阅他的网站

template<int N>
struct flag {
  friend constexpr int adl_flag …
Run Code Online (Sandbox Code Playgroud)

c++ counter friend-function argument-dependent-lookup constexpr

32
推荐指数
1
解决办法
6506
查看次数

在编译时用C++生成随机数

我正在尝试random在编译时使用C++ 11的库预先计算随机值.我主要是按照例子.我在这做错了什么?

using namespace std;
#include <iostream>
#include <vector>
#include <random>

vector<double> rands;
typedef std::mt19937_64 RNG;
uint64_t seed_val;
RNG rng; 

void initialize() {
     rng.seed(seed_val);
}

constexpr vector<double> generate_random( )                 //size_t numbers)
{   
    int numbers = 1000;
    std::uniform_real_distribution<double> zero_one(0.0, 1.0);
        for (unsigned int i = 0; i < numbers; i++) { 
             double rand_num = zero_one(rng);
             rands.push_back( rand_num );
    }
    return rands;
}

int main()
{
    cout << "TMP rands";
    for_each( rands.begin(), rands.end(), [] (double value)
    {
        cout<<value<<endl;
    });
} …
Run Code Online (Sandbox Code Playgroud)

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

24
推荐指数
4
解决办法
1万
查看次数

如何写`is_complete`模板?

回答完这个问题后,我试图is_complete在Boost库中找到模板,我意识到Boost.TypeTraits中没有这样的模板.为什么Boost库中没有这样的模板?应该怎么样?

//! Check whether type complete
template<typename T>
struct is_complete
{   
  static const bool value = ( sizeof(T) > 0 );
};

...

// so I could use it in such a way
BOOST_STATIC_ASSERT( boost::is_complete<T>::value );
Run Code Online (Sandbox Code Playgroud)

上面的代码不正确,因为应用于sizeof不完整类型是非法的.什么是好的解决方案?在某种程度上可以在这种情况下应用SFINAE吗?


嗯,这个问题一般不会在不违反ODR规则的情况下解决,但是有一个特定于平台的解决方案对我有用.

c++ templates type-traits

21
推荐指数
4
解决办法
3303
查看次数

如何在编译时生成密集的唯一类型ID?

我正在尝试创建一个小型对象的类系统,并且基类的成员是标识该类的唯一标识符:

class Shape
{
public:
    unsigned char id;
};

template <typename T>
class Triangle : public Shape
{
    T triangle_data;
};

template <typename T>
class Square : public Shape
{
    T square_data;
};

template <typename T>
class ShapeBox : public Shape
{
    T shapebox_data;
    Shape * child_shape;
};
Run Code Online (Sandbox Code Playgroud)

使用类标识符,我通过Shape*的向量并切换基类中可见的id,然后针对不同的行为进行静态转换(分别为示例类层次结构中的Triangle,Square或ShapeBox和子形状) )

我可以打开RTTI,但是空间成本似乎相当大,特别是当类型信息可以实现为指针并且对象大小可能不大于几个字节时.可能有数百万个小物件,我真的只需要静态铸造.

目前,我可以使用从静态单调递增计数器分配值的静态来创建类型标识符:

class TypeID
{
    static size_t counter;

public:
    template<typename T>
    static size_t value()
    {
        static size_t id = counter++;
        return id;
    }
};
size_t TypeID::counter = 1;
Run Code Online (Sandbox Code Playgroud)

理想情况下,我需要在编译时可用的密集,唯一类型ID,因此编译器可以很好地执行,例如将类型ID上的开关转换为常量时间跳转表,或者至少是二进制搜索树而不是线性时间/ else链可能是一长串的类型ID列表... …

c++ templates

10
推荐指数
1
解决办法
4327
查看次数

在编译时生成唯一的数字

我想为我的标题中的每个类生成唯一的数字,在我的案例中为素数,但是假设这应该只是连续的数字,即1,2,3,4等.

当然我可以硬编码:

struct A { enum { ID = 1; }; };
struct B { enum { ID = 2; }; };
struct C { enum { ID = 3; }; };
struct D { enum { ID = 4; }; };
Run Code Online (Sandbox Code Playgroud)

这非常容易出错,因为实际上类不是那么小,如果我在中间添加一个新类,如果我不想完全忽略ID的概述,我必须更改以下所有数字.

我希望我能做到以下几点:

struct A { enum { ID = get_next_int(); }; };
struct B { enum { ID = get_next_int(); }; };
struct C { enum { ID = get_next_int(); }; };
struct D { enum { ID …
Run Code Online (Sandbox Code Playgroud)

c++ metaprogramming side-effects compile-time c++11

8
推荐指数
1
解决办法
6463
查看次数

类型扣除时间

我今天早些时候遇到了这个问题.在以下代码中:

template <int> struct Holder {};

template <typename> struct Helper { using T = Holder<__COUNTER__>; };  // ???

int main() {
  auto a = typename Helper<bool>::T();
  auto b = typename Helper<int>::T();

  std::cout << (typeid(a) == typeid(b)) << std::endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译和执行时:

g++ test.cpp -std=c++11 -o test
./test
Run Code Online (Sandbox Code Playgroud)

它打印出1而不是0,这意味着2 Ts Helper<int>Helper<bool>是相同的类型,这让我想知道:

  1. 为什么标记的行// ???只对每种类型执行一次而不是一次?
  2. 有没有办法强制为每种类型执行一次行,最好不修改Holder的定义?

================================================== == 澄清:

(更接近)真实场景是:

  1. struct Holder在第三方库的标头中定义.结构的类型实际上非常复杂,库编写器为用户提供了另一个宏:
template <bool, int> struct Holder {};

#define DEF_HOLDER(b)  Holder<b, __COUNTER__>()
Run Code Online (Sandbox Code Playgroud)

在程序的某个时刻,我想通过对类型进行别名来获取具有当前计数器的类型的"快照",以便可以在函数中使用它:

template <bool …
Run Code Online (Sandbox Code Playgroud)

c++ templates c-preprocessor

8
推荐指数
1
解决办法
556
查看次数

在 GCC 8 上工作的 Constexpr 计数器,并且不限于命名空间范围

我正在尝试学习一些神秘的有状态模板元编程技巧。
(这就是我想学习它的原因。不幸的是,这个库在 GCC 8 和 Clang 上都不起作用。)

我需要的第一个明显的东西是一个constexpr计数器:

/*something*/ constexpr int foo() /*something*/

int main()
{
    constexpr int a = foo();
    constexpr int b = foo();
    constexpr int c = foo();
    static_assert(a == 0 && b == 1 && c == 2);
}
Run Code Online (Sandbox Code Playgroud)

最好它应该是一个标记的计数器,以便我可以同时拥有多个计数器:

/*something*/ constexpr int foo() /*something*/

struct TagA {};
struct TagB {};

int main()
{
    constexpr int a = foo<TagA>();
    constexpr int b = foo<TagA>();
    constexpr int c = foo<TagA>();

    constexpr …
Run Code Online (Sandbox Code Playgroud)

c++ template-meta-programming c++17

7
推荐指数
1
解决办法
1341
查看次数

编译时模板`std :: integral_constant`计数器 - 如何实现它?

我有几种类型,我想std::integral_constant在编译时将一个顺序ID值"绑定" 到每个类型.

例:

struct Type00 { };
struct Type01 { };
struct Type02 { };
struct Type03 { };
struct TypeXX { };
struct TypeYY { };

template<typename T> struct TypeInfo
{
    using Id = std::integral_constant<int, ???>;
};

int main()
{
     cout << TypeInfo<Type00>::Id::value; // Should always print 0
     cout << TypeInfo<Type01>::Id::value; // Should always print 1
     cout << TypeInfo<Type02>::Id::value; // Should always print 2
     cout << TypeInfo<Type03>::Id::value; // Should always print 3
     cout << TypeInfo<TypeXX>::Id::value; // Should …
Run Code Online (Sandbox Code Playgroud)

c++ templates constexpr c++11 c++14

6
推荐指数
1
解决办法
927
查看次数

在编译时检查字符的唯一性

是否有可能在C++ 11(不是更晚)中编写一个函数来验证在编译时传递给它的字符的唯一性

verify('a');
verify('b');
verify('c');
verify('a');  //should cause compilation error
Run Code Online (Sandbox Code Playgroud)

[由MK编辑以回答一些问题]:

  • 呼叫始终在相同的范围内,如上所述一个接一个.
  • 宏观解决方案也是可以接受的
  • 非类型模板参数也是可接受的

c++ compile-time constexpr c++11

6
推荐指数
2
解决办法
203
查看次数