我们在项目中有一个特殊的接口框架,部分要求是代表接口的类只能用作虚拟基类,而不能用作非虚拟基类.有没有办法在代码中强制执行此操作?也就是说,如果类是从非虚拟派生的,则产生编译错误.
我可以访问由VS 2010实现的C++ 11:这意味着static_assert,enable_if并且<type_traits>可用.
鉴于以下内容
#include <array>
struct litmus final : std::array<unsigned char, 16>
{
};
static_assert(std::is_pod<std::array<unsigned char, 16> >::value, "not pod");
// this fails on MSVC:
static_assert(std::is_pod<litmus>::value, "not pod");
Run Code Online (Sandbox Code Playgroud)
以下编译器同意litmuspod:
但是,MSVC12(VS2013 RTM)认为第二个断言失败.
编辑有关信息:
is_trivially_copyable<litmus>在MSVC上返回true-ness.对于许多不严格要求实际POD的情况,这可能很有用.
为什么Visual Studio 2013编译器拒绝第一个静态断言(错误C2057),而不是第二个?
#include <limits>
typedef int Frequency;
const Frequency minHz{ 0 };
const Frequency maxHz{ std::numeric_limits<Frequency>::max() };
const Frequency invalidHz{ -1 };
static_assert(minHz < maxHz, "minHz must be less than maxHz"); // C2057
static_assert(invalidHz < minHz || invalidHz > maxHz, "invalidHz is valid"); // OK
Run Code Online (Sandbox Code Playgroud) 我想明确关于成员变量的数组大小限制,以阻止其他人意外地进行愚蠢的更改.以下天真的尝试将无法编译:
struct Foo
{
std::array< int, 1024 > some_array;
static_assert( (some_array.size() % 256) == 0, "Size must be multiple of 256" );
//^ (clang) error: invalid use of non-static data member 'some_array'
};
Run Code Online (Sandbox Code Playgroud)
即使std::array::size是constexpr,我也不能直接使用static_assert,因为函数和我的成员变量都不是静态的.
我想出的解决方案是使用decltype(因为我不想键入数组),如下所示:
static_assert( (decltype(some_array)().size() % 256) == 0, "Size must be multiple of 256" );
Run Code Online (Sandbox Code Playgroud)
这看起来像是默认构造一个右值,我认为它不是一个constexpr.
为什么这样做?
有没有更简洁的方法来实现静态断言?
静态断言声明可能出现在块作用域(作为块声明)和类体内(作为成员声明)
好的,现在我有以下代码:
struct foo_t
{
static constexpr std::size_t maxAlignment()
{
// This is just a sample; I removed real code from this method.
return std::max(alignof(__m128), __alignof(__m256));
}
static_assert(0 == ((maxAlignment() -1) & maxAlignment()), "some message");
};
Run Code Online (Sandbox Code Playgroud)
MSVC 2015和Intel C++ 16.0.2都没有编译此代码(前者显示"错误C2131:表达式未评估为常量",后者显示"函数调用必须在常量表达式中具有常量值"错误并指向调用maxAlignmentin static_assert).
但MSVC 2015 Update 1 确实编译了以下代码,而英特尔C++ 16.0.2 则没有:
template <typename T, std::size_t Alignment>
struct foo_t
{
static constexpr std::size_t maxAlignment()
{
return std::max(std::alignment_of<T>::value, Alignment);
}
static_assert(0 == ((maxAlignment() -1) & …Run Code Online (Sandbox Code Playgroud) 假设我们要创建一个只能用数字实例化的模板类,否则就不应该编译。我的尝试:
#include <type_traits>
template<typename T, typename = void>
struct OnlyNumbers{
public:
struct C{};
static_assert(std::is_same<C,T>::value, "T is not arithmetic type.");
//OnlyNumbers<C>* ptr;
};
template<typename T>
struct OnlyNumbers<T, std::enable_if_t<std::is_arithmetic_v<T>>>{};
struct Foo{};
int main()
{
OnlyNumbers<int>{}; //Compiles
//OnlyNumbers<Foo>{}; //Error
}
Run Code Online (Sandbox Code Playgroud)
现场演示 -所有三个主要的编译器似乎都能按预期工作。我知道已经有一个类似的问题,答案引用了该标准。接受的答案使用temp.res.8和temp.dep.1来回答该问题。我认为我的问题有所不同,因为我只是在问我的示例,我不确定标准对此的看法。
我认为我的程序不是格式错误的,并且仅当编译器尝试实例化基本模板时,它才应该无法编译。我的推理:
[temp.dep.1]:
在模板内部,某些构造的语义可能因一个实例而异。这样的构造取决于模板参数。
这应该使std::is_same<C,T>::value依赖T。
[temp.res.8.1]:
如果模板中的语句或模板未实例化,则无法为模板或constexpr的子语句生成有效的专业化名称;或者
不适用,因为存在有效的专业化,尤其OnlyNumbers<C>是有效的,并且可以在类内部用于例如定义成员指针variable(ptr)。实际上,通过删除断言并取消注释ptr,OnlyNumbers<Foo>代码行得以编译。
[temp.res.8.2-8.4]不适用。
我的问题是:我的推理正确吗?这是一种使特定[class] *模板static_assert仅在实例化时无法编译的安全,符合标准的方法吗?
*基本上,我对类模板感兴趣,请随时包含函数模板。但是我认为规则是相同的。
**这意味着没有T像T=C从内部使用那样可以从外部实例化模板。即使C可以通过某种方式访问,我也不认为有一种方法可以引用它,因为它会导致这种递归OnlyNumbers<OnlyNumbers<...>::C> …
我想确保派生类实现一个特定的静态方法.我认为这样做应该可以使用static_assert,std :: is_same,decltype,CRTP并且可能使用SFINAE.但是,到目前为止,我发现的类似代码非常复杂,似乎我还没有完全理解它使我无法将其用于我的需求.
到目前为止我尝试过的是这个
template <class T>
class Base
{
static_assert(std::is_same<decltype(T::foo(1)), int>::value, "ERROR STRING");
};
class Derived : public Base <Derived>
{
public:
static int foo(int i) { return 42; };
};
Run Code Online (Sandbox Code Playgroud)
但是,它没有编译告诉我,即使方法正确实现,Derived也没有名为foo的元素.此外,在static_assert内的表达式中为foo提供实际参数会感觉不对.
搜索SO揭示了一个类似的问题,最终引导我到这段代码,检查一个类型有方法begin()和end()返回迭代器.所以我试着采用这个代码来满足我的需求.
template <class T>
class Base
{
template<typename C>
static char(&g(typename std::enable_if<std::is_same<decltype(static_cast<int(C::*)(int)>(&C::foo)), int(C::*)(int)>::value, void>::type*))[1];
template<typename C>
static char(&g(...))[2];
static_assert(sizeof(g<T>(0)) == 1, "ERROR STRING");
};
Run Code Online (Sandbox Code Playgroud)
但是这段代码没有编译,因为断言触发了.
所以我的问题是
typename C::const_iterator(C::*)() const示例代码到底意味着什么?是不是一个const函数返回C …假设一个模板类,我们在编译时断言整数模板参数必须大于零:
template<int N>
class A
{
public:
A() {
static_assert(N > 0, "N needs to be greater 0.");
}
};
Run Code Online (Sandbox Code Playgroud)
是否可以创建一个可编译但在运行时报告错误的 googletest 单元测试?例如:
TEST(TestA, ConstructionNotAllowedWithZero)
{
ASSERT_DOES_NOT_COMPILE(
{
A< 0 > a;
}
);
}
Run Code Online (Sandbox Code Playgroud) 我有一个用户定义的文字运算符,它只对特定长度的字符串有意义,如下所示:
constexpr uint16_t operator "" _int(const char* s, std::size_t len)
{
return len == 2 ? s[0] | (s[1] << 8) : throw;
}
Run Code Online (Sandbox Code Playgroud)
这有效:
"AB"_int // equals 16961
Run Code Online (Sandbox Code Playgroud)
但这也可以编译,我不希望它:
"ABC"_int // throws at runtime
Run Code Online (Sandbox Code Playgroud)
我试过了static_assert(len == 2),但在 constexpr 函数中是不允许的。
如何"ABC"_int在编译时导致错误?
c++ static-assert compile-time-constant user-defined-literals c++11
我昨天读了几个关于在an 子句中使用的答案。我知道根据标准,它被认为是格式错误的(即使某些编译器,包括 MSVC2017,会接受它)。Qt 也会将此标记为错误。static_assert(false, "Some message")elseif constexpr
我的问题是,下面的代码是否符合标准?(我倾向于这么认为,但我想确认一下。)
template <typename TypeOfValue>
static void PushValue(duk_context* ctx, TypeOfValue value) {
// Push value onto duktape stack
if constexpr (std::is_same<TypeOfValue, int>::value) {
// Push int
duk_push_int(ctx, value);
} else if constexpr (std::is_same<TypeOfValue, uint32_t>::value) {
// Push uint
duk_push_uint(ctx, value);
} else {
// Unsupported type
static_assert(bool_value<false, TypeOfValue>(), "Unsupported type");
}
}
template <bool value, typename T>
static constexpr bool bool_value() {return value;}
Run Code Online (Sandbox Code Playgroud)
编辑: …
c++ ×10
static-assert ×10
c++11 ×5
type-traits ×2
visual-c++ ×2
clang ×1
constexpr ×1
crtp ×1
googletest ×1
icc ×1
if-constexpr ×1
pod ×1
stdarray ×1
templates ×1