我正在尝试定义一个模板类,它具有用户定义类型的非类型模板参数.不幸的是,迄今没有成功.真正的代码有点过于冗长,但简化示例如下所示:
#include <iostream>
template <class T>
class Maybe {
bool is_ = false;
T value_;
public:
constexpr Maybe() = default;
constexpr Maybe(T value) : is_(true), value_(value) {}
constexpr bool is() const { return is_; }
};
template <Maybe<int> parm>
struct Test {
void say() const {
std::cout << "parm is " << (parm.is() ? "set" : "not set") << ".\n";
}
};
int main() {
Test<Maybe<int>{}> not_set;
Test<Maybe<int>(2)> is_set;
not_set.say();
is_set.say();
}
Run Code Online (Sandbox Code Playgroud)
当我尝试编译此代码(使用Clang 3.4)时,我收到以下错误消息:
test.cc:15:22: error: a non-type template parameter …Run Code Online (Sandbox Code Playgroud) 我知道MSVS2013(甚至是CTP)无法处理static constexpr double数据成员,正如这个问题所证实的那样.
现在,我希望MSVS2015 Preview能够让我至少使用这个简单的构造,但是,我得到了同样的错误.所以逻辑上的下一个问题是:有没有办法用MSVC2015定义编译时双精度常量?
例:
template<typename T>
struct my_constant
{
static constexpr const T value = 42;
}
Run Code Online (Sandbox Code Playgroud)
这给出了错误:
error C2864: 'my_constant<double>::value': a static data member with an in-class initializer must have non-volatile const integral type
Run Code Online (Sandbox Code Playgroud)
这是C++ 03 mumbo-jumbo.
精简版:
如果我有这样的功能:
constexpr bool has_some_property(Foo) { return true; }
Run Code Online (Sandbox Code Playgroud)
有没有办法调用函数而不必实际实例化Foo?如果Foo不是默认可构造的话?
长卷版本:
安东尼威廉姆斯最近写了一篇文章,详细介绍了一套为任何enum class专门用于特定模板的对象启用的免费功能.它遵循类似的方案中<ios>,std::is_error_code其中一个专门用于用户定义的类型或值的模板,以允许enable_if启用某些功能.在Anthony的案例中:
template<>
struct enable_bitmask_operators<my_bitmask>{
static constexpr bool enable=true;
};
Run Code Online (Sandbox Code Playgroud)
然后在定义运算符时:
template<typename E>
typename std::enable_if<enable_bitmask_operators<E>::enable,E>::type
operator|(E lhs,E rhs){
Run Code Online (Sandbox Code Playgroud)
此技术的问题是模板特化必须与原始模板位于同一名称空间中,因此这不起作用:
namespace mystuff {
enum class Foo {
...
};
// Fail: wrong namespace
template<>
struct enable_bitmask_operators<Foo> : std::true_type {}
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用一个constexpr函数,该函数可以在与类相同的命名空间中解析:
namespace mystuff {
enum class Foo {
...
};
constexpr bool enable_bitmask_operators(Foo) { return …Run Code Online (Sandbox Code Playgroud) B. Stroustrup在他的书"TCPL"第4版的第265页上有以下例子:
struct Point{
int x, y, z;
constexpr Point up(int d) { return {x, y, z+d}; }
constexpr Poind move(int dx, int dy) { return {x+dx, y+dy}; }
};
Run Code Online (Sandbox Code Playgroud)
后来他在第266页显示:
constexpr Point p1 {10, 20, 30}; // the default constructor is constexpr
Run Code Online (Sandbox Code Playgroud)
从N4140的§7.1.5/ 4开始,我发现了以下相关要点:
- (4.4)其函数体应为
= default,或其函数体的复合语句应满足constexpr函数的函数体的约束;- (4.5)应初始化每个非变量非静态数据成员和基类子对象(12.6.2);
关于上面的要点,我有两点意见:
struct Point具有函数体是否正确= default?yes,我也在争论编译器为struct Pointis 生成默认构造函数的事实,constexpr因为这个构造函数没有初始化成员x,y并且z与上面的项目符号(4.5)相矛盾.我在这里纠正吗?编辑我正在介绍第三个问题,我认为总结了我在这个问题上遇到的主要困难.
我无法生成constexpr其body等于的默认构造函数的示例= default …
我的应用包含大量ID.我想最终让其他人可以查看代码,但是不要让运行时反向工程师轻松查找容易知道的ID.此外,在开发期间,在日志文件中具有常量ID以便于调试是有帮助的.但是在运行时我想通过在Release编译期间生成这些ID来使它们随机.使用<random>lib的建议代码可以在GetRandomId1()下面看到.constexpr像在switch语句中那样在代码中使用它们.但是,我constexpr在提议的功能中使用时遇到了问题,因为<random>它不constexpr兼容.还有另一种在编译时生成随机数的方法吗?或者是在编译时生成随机数,以便在运行时用作常量来考虑constexpr?
#include <iostream>
#include <random>
// this is the code I would like to use to generate a random number at compile time
/*constexpr */int GetRandomId1()
{
std::random_device rd; // non-deterministic seed
std::mt19937 gen( rd() ); // with constexpr uncommented:
// error C3250: 'rd': declaration is not allowed in 'constexpr' function body
// error C3249: illegal statement or sub-expression for 'constexpr' function
// error C3250: 'gen': …Run Code Online (Sandbox Code Playgroud) 我正在尝试编译以下代码:
enum class Order : char
{
Little,
Big
};
constexpr Order get_order() {
uint16_t x = 1;
return *((uint8_t *) &x) == 0 ? Order::Big : Order::Little;
}
Run Code Online (Sandbox Code Playgroud)
我用-std=c++14标志做到这一点,但我得到了这个错误:
在函数'constexpr byteorder :: Order byteorder :: get_order()'中:/home/user/dev/c++/render/include/byteorder.h:19:1:error:constexpr function'constexpr byteorder :: Order byteorder :: get_order()'不是返回语句
看起来像c ++ 11!
如果c ++ 14在constexpr函数中允许局部变量怎么办?
Debian Jessie,gcc 4.9.2
严格按照C++ 14的规则,至少cppreference.com给出的规则,不是第(1)行是一个常量表达式吗?
constexpr const int* addr(const int& ir) { return &ir; }
constexpr const int* tp = addr(5); // (1)
Run Code Online (Sandbox Code Playgroud)
确实,它不是地址常量表达式,因为&ir它不是静态对象&ir的地址(在此上下文中是临时的地址,在编译时无法知道).
但它是一个核心常量表达式,因为它不违反任何后面列出的核心常量表达式规则,它没有关于获取对象地址的后续规则.
我正在尝试实现一个在编译时执行字符串哈希的类,如果给出了文字字符串,或者运行时(基于本文).我不是像作者那样使用FNV-1a而是使用xxHash(64bits),因为编译时计算我正在使用这段代码.
这是我的实现:
class StringHash {
public:
class ConstCharWrapper {
public:
inline ConstCharWrapper( const char *Str ) : Internal(Str) {}
const char *Internal;
};
template <size_t N>
__forceinline StringHash( const char (&Str)[N] ) :
m_Hash( std::integral_constant<uint64_t, xxh64::hash(Str, N-1)>::value )
{
}
inline StringHash( ConstCharWrapper Str ) :
m_Hash( xxHash_64::Calc((const uint8_t*)Str.Internal, strlen(Str.Internal)) )
{
}
inline StringHash( const char *Str, size_t Length ) :
m_Hash( xxHash_64::Calc((const uint8_t*)Str, Length) )
{
}
__forceinline operator uint64_t() const { …Run Code Online (Sandbox Code Playgroud) 最近,我修改了一些if constexpr到if我constexpr功能,发现他们仍然正常工作,并能进行评估时,编译时间.这是一个最小的案例:
template<int N>
constexpr bool is_negative()
{
if constexpr (N >= 0) return false;
else return true;
}
int main()
{
constexpr bool v = is_negative<1>();
}
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,N必须在编译时知道因为它是非类型模板参数,所以if constexpr在这里工作正常.然而,这是一个constexpr功能,因此,IIRC,它是可以让即使我更换一个返回值if constexpr有if:
template<int N>
constexpr bool is_negative()
{
if (N >= 0) return false;
else return true;
}
int main()
{
constexpr bool v = is_negative<1>();
}
Run Code Online (Sandbox Code Playgroud)
从cppref来看,所有的要求A constexpr function …
template<int N>
void f()
{
constexpr int n = 9;
++*const_cast<int*>(&n); // ok
++*const_cast<int*>(&N); // error C2101: '&' on constant
}
int main()
{
f<8>();
}
Run Code Online (Sandbox Code Playgroud)
根据cppref:
变量,函数,模板参数对象(自C ++ 20起)或数据成员的名称,无论类型如何,例如std :: cin或std :: endl。即使变量的类型是右值引用,由其名称组成的表达式也是左值表达式。
两个问题:
1.为什么vc ++ 2019(带有/ std:c ++ latest)不接受代码?
2.为什么C ++ 20允许模板参数对象为左值?
constexpr ×10
c++ ×9
c++11 ×5
c++14 ×3
templates ×2
visual-c++ ×2
c++20 ×1
compile-time ×1
const ×1
if-constexpr ×1
random ×1