我一直在使用(并且看到用过)static_assert来标记模板参数值的不需要的值.然而,对于我遇到的所有情况,通过SFINAE禁用那些不需要的值似乎更好,更优雅.例如
template<typename T,
class = std::enable_if<std::is_floating_point<T>::value>::type>
struct Foo { ... };
Run Code Online (Sandbox Code Playgroud)
代替
template<typename T>
struct Foo {
static_assert(std::is_floating_point<T>::value,
"Foo<T>: T must be floating point :-(");
...
};
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:何时使用static_assert而不是SFINAE?为什么?
编辑
我认为到目前为止我所学到的是以下内容
1 SFINAE是一个多功能且功能强大但可能非常复杂的工具,可用于许多任务,包括功能过载解决(有些人认为这是其唯一目的).
2 SFINAE可以以一种相对简单的方式使用static_assert,除非它出现在(类或函数的)声明中而不是它的定义(或者是否可以插入static_assert一个类,例如,类前向声明?) .这使得更加逐字,更清晰的代码.然而,因为SFINAE很复杂,所以它往往比简单的更难static_assert.
3另一方面,static_assert有一个更清晰的编译器错误消息的好处,有些人似乎认为这两者的主要目的.
我想知道是否有可能在编译时检查两种类型是否相同.我想出的是(idk如果它有效,因为它感觉hackish和IDK标准好,所以IDK在测试时要寻找什么).
#include <boost/strong_typedef.hpp>
BOOST_STRONG_TYPEDEF(double, cm);
BOOST_STRONG_TYPEDEF(double, inch);
template<typename T, typename U>
static constexpr void __help()
{
}
template<typename T, typename U>
class AreSameType
{
public:
constexpr operator bool()
{
return &__help<T,U> == &__help<U,T>;
};
};
Run Code Online (Sandbox Code Playgroud)
用法:
int main()
{
static_assert(AreSameType<double,float>()== false, "oh noes1");
static_assert(AreSameType<double,double>()== true, "oh noes2");
static_assert(AreSameType<int*,double*>()== false, "oh noes3");
static_assert(AreSameType<double*,double>()== false, "oh noes4");
static_assert(AreSameType<const double,double>()== false, "oh noes5");
static_assert(AreSameType<inch,cm>()== true, "oh expected"); //fires
}
Run Code Online (Sandbox Code Playgroud)
所以
1)有更好的方法吗?
2)这个功能黑客的地址保证按标准工作(我打赌不会:))?
这个问题已经讨论了几次,但我发现的所有解决方案要么不起作用,要么基于boost的静态断言.我的问题很简单.我有一个类,我只想允许真正的类型(double和float).如果我尝试使用float或double以外的类型实例化类,我想要一个编译时错误.我正在使用Visual C++ 11.这是我尝试过的:
template <typename RealType>
class A
{
// Warning C4346
static_assert(std::is_same<RealType, double>::value || std::is_same<RealType, float>::value);
}
template <typename RealType>
class A
{
// Error C2062: type 'unknown' unexpected
static_assert(decltype(RealType) == double || decltype(RealType) == float);
}
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?提前致谢!
我有一个我static_assert的模板结构的移动构造函数.这是否static_assert需要编译器考虑,即使可以复制省略?
这是精简的场景:
#include <type_traits>
template<typename T>
struct X
{
X(X&&) { static_assert(std::is_same<void, T>::value, "Intentional Failure"); }
};
auto impl() -> X<int>;
auto test() -> decltype(impl())
{
return impl();
}
int main()
{
test();
}
Run Code Online (Sandbox Code Playgroud)
GCC和Clang同意评估static_assert并且无法编译.
另一方面,MSCV和ICC编译代码就好了.
有趣的是,当我删除move构造函数的定义时,只需将其声明为:
template<typename T>
struct X
{
X(X&&);
};
Run Code Online (Sandbox Code Playgroud)
GCC和Clang现在也编译代码.因此,所有编译器似乎都同意移动构造函数的定义与复制省略无关.
问题:
如果static_assert复制/移动构造函数中有a ,即使可以复制/移动省略,标准是否要求对其进行评估?
我想创建一个类模板
template <class T>
class X {
// here I'll use T::value (among other things)
};
Run Code Online (Sandbox Code Playgroud)
T::value通常是constexpr静态变量,但并非总是如此.T::value必须是正值,所以我想在编译期间让人们知道它,如果可能的话.
如果T::value总是constexpr,我会添加static_assert喜欢
static_assert(T::value > 0, "need positive number");
Run Code Online (Sandbox Code Playgroud)
是否可以仅在T::valueconstexpr的情况下添加此static_assert ?
由于在我工作的公司中禁止使用boost,我需要在纯C++中实现其功能.我已经研究了增强源,但它们似乎太复杂了,至少对我而言.我知道static_assert()在C++ 0x标准中有一些东西,但我不想使用任何C++ 0x功能.
在C++ 11中,编写是合法的,例如:
int b = (some_function_returning_void(), 1020);
Run Code Online (Sandbox Code Playgroud)
你会回来1020.但它不会让你写:
int b = (static_assert(2 > 1, "all is lost"), 304);
Run Code Online (Sandbox Code Playgroud)
该文档解释了static_assert(显然是一个关键字)可能出现的合法位置:
静态断言声明可能出现在块作用域(作为块声明)和类体内(作为成员声明)
只是为了它,我尝试了几件事,直到这个工作:
int b = ({static_assert(2 > 1, "all is lost"); 304;});
Run Code Online (Sandbox Code Playgroud)
但随着-Wpedantic我的到来"warning: ISO C++ forbids braced-groups within expressions".有趣的是,这些被称为"语句表达式"并在Linux内核中使用.
但我们想象一下,我想留下来-Wpedantic.有没有干净的解决方法?
我想要一个C++ 0x static_assert来测试给定的结构类型是否是POD(以防止其他程序员无意中用新成员破坏它).即
struct A // is a POD type
{
int x,y,z;
}
struct B // is not a POD type (has a nondefault ctor)
{
int x,y,z;
B( int _x, int _y, int _z ) : x(_x), y(_y), z(_z) {}
}
void CompileTimeAsserts()
{
static_assert( is_pod_type( A ) , "This assert should not fire." );
static_assert( is_pod_type( B ) , "This assert will fire and scold whoever added a ctor to the POD type." ); …Run Code Online (Sandbox Code Playgroud) 我的内部健全性检查失败,所以我在Stackoverflow上重新运行它.
以下代码:
#include <iostream>
#include <typeinfo>
#include <utility>
int main()
{
constexpr auto pair_of_ints = std::make_pair(1, 2);
std::cerr << typeid(pair_of_ints).name();
//static_assert(std::is_same<decltype(pair_of_ints), std::pair<int, int>>::value, "WTF");
}
Run Code Online (Sandbox Code Playgroud)
std::__1::pair<int, int>在我的系统上生成受损的符号名称(XCode Clang 8.x).
如果我然后启用它static_assert,则失败.我不知道为什么.我怎样才能做到这一点?我有一个函数,它返回一个对或元组,具体取决于传递给它的参数,并希望验证它在正确的情况下实际返回一对或元组.
我试图禁止对volatile类型进行特定操作.为了实现这一点,我试图使用std::is_volatile,但下面的代码编译没有错误,这不是我想要的.
为什么在下面的情况下是is_volatile::value 假的?
#include <type_traits>
template<typename T>
inline void DoStuff(T val) {
static_assert(!std::is_volatile<T>::value, "No volatile types plz");
//...
}
int main() {
volatile char sometext[261];
DoStuff(sometext);
}
Run Code Online (Sandbox Code Playgroud) c++ ×10
static-assert ×10
c++11 ×8
templates ×3
sfinae ×2
type-traits ×2
boost ×1
constexpr ×1
copy-elision ×1
replace ×1
std-pair ×1