所以我尝试使用自定义文字运算符来实现二进制文字.但是,似乎我在模板专业化方面做错了.static_assert是在不应该:
template <char... bits>
struct bin_imp
{
static constexpr unsigned long long to_ull()
{
static_assert(false,"not binary value");
return 0;
}
};
template <char... bits>
struct bin_imp<'0', bits...>
{
static constexpr unsigned long long to_ull()
{
return bin_imp<bits...>::to_ull();
}
};
template <char... bits>
struct bin_imp<'1', bits...>
{
static constexpr unsigned long long to_ull()
{
return (1ULL << sizeof...(bits)) | bin_imp<bits...>::to_ull();
}
};
template <>
struct bin_imp<>
{
static constexpr unsigned long long to_ull()
{
return 0;
}
};
template <char... bits> …Run Code Online (Sandbox Code Playgroud) c++ templates static-assert template-specialization variadic-templates
在 Visual Studio 中尝试编译时,我得到一个 static_assert,但是当我单击该错误时,它需要断言本身而不是有问题的行。
如何找出哪一行触发了static_assert?
我有一个带有整数模板参数的函数模板。我想仅提供特定整数的实现。尝试将函数模板与另一个参数一起使用应该会导致编译错误。
我static_assert以下面介绍的方式使用。
#include <type_traits>
#include <iostream>
template <typename T>
struct false_type : public std::false_type {};
template <int T>
void function() {
static_assert(false_type<decltype(T)>::value, "Error");
};
template <>
void function<1>() {
std::cout << 1 << std::endl;
}
int main() {
function<1>();
}
Run Code Online (Sandbox Code Playgroud)
该代码运行良好,直到gcc 9.1它给出一个error: static assertion failed.
我想知道是否有一种技术可以实现我的目标并且与 兼容gcc 9.1?
_Static_assert内置于某些 C 编译器(例如 gcc 和 clang)中,但可能并非所有 C 编译器都包含它。我想在使用该_Static_assert功能的同时尽可能保持我的代码跨平台。我认为最好的方法是测试
#ifdef _Static_assert
_Static_assert(0, "Test");
#endif
Run Code Online (Sandbox Code Playgroud)
但这似乎行不通。它编译,但它没有检测到_Static_assert已定义。然后我想我可以测试编译器是否是 GCC,但我读到__GNUC__定义并不一定证明使用的编译器是 GCC。这也没有检测_Static_assert到我可能不知道的其他编译器。所以我的问题是,检测编译器是否支持_Static_assert预处理器的最佳方法是什么?
编辑:这是我想出的适合我的目的的解决方案。感谢下面的@KamilCuk 提供帮助我的链接。
// Check that we can use built-in _Static_assert
#if defined( __STDC_VERSION__ ) && __STDC_VERSION__ >= 201112L
#define WE_HAVE_STATIC_ASSERT 1
#endif
#if WE_HAVE_STATIC_ASSERT
_Static_assert(0, "Test");
#endif
Run Code Online (Sandbox Code Playgroud)
这段代码在 gcc 和 clang 上都适用于我:https : //godbolt.org/z/svaYjWj4j
最终编辑(我认为):这为我关于如何检测是否_Static_assert可用的原始问题提供了答案。它还提供了一个回退选项,可以在我测试的大多数编译器中产生相对有用的错误。
这是测试代码的链接:https : //godbolt.org/z/TYEj7Tezd
// Check if we can use built-in …Run Code Online (Sandbox Code Playgroud) 我试图在编译时确定特定类型是否为std::pair类型。当我编译下面的代码时,我在两个分支(即“HERE1”和“HERE2”)上的断言都失败了。如果我删除static_asserts并取消打印,我得到了我期待:那就是“HERE1”为is_pair_type <T :: VALUE_TYPE>和“HERE2”为is_pair_type <T> 。
我想这意味着编译器无法在编译时评估表达式,但我不明白为什么。
使用:MS VS2019,MSVC 版本 14.29.30037
谢谢。
template< class T > struct is_pair : std::false_type {};
template< class T1, class T2 > struct is_pair< std::pair< T1, T2 > > : std::true_type {};
template< class T > struct is_pair_d : is_pair<typename std::decay<T>::type> {};
// a helper function for value
template<class T> struct is_pair_type {
static constexpr bool const value = is_pair_d<T>::value;
};
int main()
{
using T = std::map<int, float>;
T …Run Code Online (Sandbox Code Playgroud) c++ static-assert type-traits c++17 compile-time-type-checking
有没有解决方法可以做这样的事情?
if constexpr (std::floating_point<T>) {}
else if constexpr (std::integral<T>) {}
...
else static_failure("Feature expansion needed");
Run Code Online (Sandbox Code Playgroud)
因为如果我替换static_failure为static_assert,它需要复制所有上述条件(它们很多而且复杂)并且它变得丑陋。
// It does not work properly: always fail
else static_assert(false, "Feature expansion needed");
// works fine, but it is ugly
else static_assert(std::floating_point<T> || std::integral<T> || ... || ... || ..., "Feature expansion needed");
Run Code Online (Sandbox Code Playgroud)
我不喜欢像这样的运行时行为:
throw "Feature expansion needed";
Run Code Online (Sandbox Code Playgroud) 假设我有3个班级.我希望sizeof()每个类都完全相同 - 比方说512个字节.
我如何使用类似的东西BOOST_STATIC_ASSERT来应用于所有这些
BOOST_STATIC_ASSERT在一个地方使用(DRY原则)注意:我们可以使用我们想要的任何C++技术(创建更多类,使用继承等)
我天真的解决方案如下:
class A { ...stuff }; BOOST_STATIC_ASSERT( sizeof(A) == 512 );
class B { ...stuff }; BOOST_STATIC_ASSERT( sizeof(B) == 512 );
class C { ...stuff }; BOOST_STATIC_ASSERT( sizeof(C) == 512 );
Run Code Online (Sandbox Code Playgroud) 我曾尝试使用此建议来执行静态断言,但如果我在模板的方法中使用它,则不会出现编译错误.
示例如下:
#include <iostream>
#define STATIC_ASSERT(expr, msg) \
{ \
char STATIC_ASSERTION__##msg[(expr)?1:-1]; \
(void)STATIC_ASSERTION__##msg[0]; \
}
template <typename T >
class A
{
public:
int foo(const int k )
{
// does not work
STATIC_ASSERT( k > 9, error_msg );
return k+5;
}
};
int bar(const int k )
{
// works fine
//STATIC_ASSERT( k > 9, error_msg );
return k+5;
}
int main()
{
A<int> a;
const int v = 2;
std::cout<<a.foo(v)<<std::endl;
std::cout<<bar(v)<<std::endl;
// works fine
//STATIC_ASSERT( …Run Code Online (Sandbox Code Playgroud) 如果USE_STATIC_ASSERT是0,则按预期工作(从列表中获取索引类型).如果1 static_assert()总是跳闸.我本以为static_assert()只有当所有人typename都筋疲力尽时才会发生.为什么不是这样?
#define USE_STATIC_ASSERT 1
template <unsigned int I, typename ...Ts>
struct items;
template <typename T, typename ...Ts>
struct items<0, T, Ts...>
{
typedef T type;
};
template <unsigned int I, typename T, typename ...Ts>
struct items<I, T, Ts...> : items<I-1, Ts...>
{
};
#if USE_STATIC_ASSERT
template <unsigned int I>
struct items<I>
{
static_assert(false, "Ran out of Ts.");
};
#endif
int main()
{
cout << is_same<float, items<1, int, float, double>::type>::value << …Run Code Online (Sandbox Code Playgroud) 所以我从一个API中获取一个变量,我们将其调用并将其long foo传递给另一个API,将其作为值:int bar.
我在视觉工作室2017年,其中实际上是相同的东西:https://docs.microsoft.com/en-us/cpp/cpp/data-type-ranges?view = vs-2017
但这会引发:
static_assert(is_same_v<decltype(foo), decltype(bar)>);
Run Code Online (Sandbox Code Playgroud)
因为即使它们实际上是相同的,它们也不是同一类型.对此有一个解决办法,不是用数字界线库匹配等long来的int?
static-assert ×10
c++ ×9
templates ×2
boost ×1
c ×1
c++11 ×1
c++17 ×1
c++98 ×1
g++ ×1
int ×1
long-integer ×1
macros ×1
type-traits ×1