鉴于以下内容:
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语句的情况.
在您尝试阅读整篇文章之前,请了解:
fameta::counter类中,以解决一些剩余的怪癖。你可以在 github 上找到它;自从 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
我正在尝试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) 回答完这个问题后,我试图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吗?
我正在尝试创建一个小型对象的类系统,并且基类的成员是标识该类的唯一标识符:
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列表... …
我想为我的标题中的每个类生成唯一的数字,在我的案例中为素数,但是假设这应该只是连续的数字,即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) 我今天早些时候遇到了这个问题.在以下代码中:
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>是相同的类型,这让我想知道:
// ???只对每种类型执行一次而不是一次?================================================== == 澄清:
(更接近)真实场景是:
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) 我正在尝试学习一些神秘的有状态模板元编程技巧。
(这就是我想学习它的原因。不幸的是,这个库在 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) 我有几种类型,我想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++ 11(不是更晚)中编写一个函数来验证在编译时传递给它的字符的唯一性
verify('a');
verify('b');
verify('c');
verify('a'); //should cause compilation error
Run Code Online (Sandbox Code Playgroud)
[由MK编辑以回答一些问题]:
c++ ×10
templates ×5
c++11 ×4
constexpr ×3
compile-time ×2
c++14 ×1
c++17 ×1
counter ×1
random ×1
side-effects ×1
type-traits ×1