static_assert 似乎是一个非常好的功能与模板.
但是,我无法在标准库中查找函数,以便在编译时进行各种测试.
例如,我正在寻找一个函数来检查类型是否是另一个类型的子类型.boost::is_base_of但是,这项工作在std中是一个类似的功能,所以我不需要依赖boost.
基本上,是否有一个很好的源代码可以在static_assertC++ 11的标准库中使用并包含在函数列表中?
什么时候static_assert执行?我可以将它放在模板中的任何位置,并针对每个模板实例进行评估吗?它可以用来将模板参数约束为类的特定子类型吗?
如何制定static_assert特定的类型约束?
目前,我只想将模板用作unsigned int类型,而不是signed int类型。或者,仅用于整数类型或特定类型名称。static_assert(sizeof(int))仅提供基于大小的断言,并且我不知道如何执行任何额外的检查。
我正在libc++Xcode 4.6.2中使用Clang及其它。这是命令行上的当前编译器信息。
Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin12.3.0
Thread model: posix
Run Code Online (Sandbox Code Playgroud) Visual Studio 2013中的以下代码导致错误C2057:
#include <cmath>
int main() {
static_assert(std::pow(2, 2) < 5, "foobar");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
错误C2057:预期的常量表达式
如果我在GCC下编译-std=c++0x它可以正常工作.http://ideone.com/2c4dj5
如果我更换std::pow(2, 2)用4,也编译的Visual Studio 2013下.
我有一个带有输出迭代器参数的函数的模板.我如何使用static_assert来检查实例化是否使用了适当的迭代器?(即,它都是输出迭代器,并且它分配了正确类型的元素.)
#include <iostream>
#include <list>
#include <set>
template <class OutputIter>
void add_ints ( OutputIter iter )
{
static_assert ( something_goes_here,
"Arg must be an output iterator over ints" );
*iter++ = 1;
*iter++ = 2;
*iter++ = 3;
}
main()
{
// Insert iterator will add three elements.
std::set<int> my_set;
add_ints ( std::inserter ( my_set, my_set.end() ) );
for ( int i : my_set ) std::cout << i << "\n";
// Non-insert iterator will overwrite three elements.
std::list<int> …Run Code Online (Sandbox Code Playgroud) 考虑以下模板:
template <typename T>
void foo() {
static_assert(sizeof(T) == 0, "Now what?");
}
Run Code Online (Sandbox Code Playgroud)
标准(第7.4节)说:
[如果static_assert的条件为false]程序格式错误,生成的诊断消息(1.4)应包含字符串文字的文本,[...]
(参考来自/sf/answers/773423451/)
实际上,在static_assert我们实例化函数模板之前不会失败foo,因为使用模板参数会强制编译器仅在两阶段查找期间评估条件.因此,除非实例化函数模板,否则上面的代码片段不会被视为格式错误.
另一方面,根据定义,C++中的 sizeof(T)> 0 .因此,条件的值实际上独立于任何模板参数!是否允许"恶意"编译器利用这一事实,并拒绝将程序视为格式错误,无论是否foo实际实例化?
我写我在哪里复制的钥匙的功能map,set,unordered_map,unordered_set的vector,现在我想添加一个编译时断言,以得到清晰的错误,如果有的试图通过一个vector,list在该功能.
template <typename container>
auto CopyKeyToVector(conatiner c)
{
//static assert to check c is map, unordered map only?
}
Run Code Online (Sandbox Code Playgroud)
任何想法,我们该怎么办但─因为map,unordered_map本身模板化的容器
我正在尝试使用static_assert来强制失败.如果您尝试以特定方式实例化特定的模板化函数,我想生成编译器错误.我可以使它工作,但它真的很难看.有更简单的方法吗?
这是我的第一次尝试.这根本不起作用.它总是会生成错误,即使没有人尝试使用此功能.
template< class T >
void marshal(std::string name, T *value)
{
static_assert(false, "You cannot marshal a pointer.");
}
Run Code Online (Sandbox Code Playgroud)
这是我的第二次尝试.它确实有效.如果你不打电话,你就不会有错误.如果您这样做,您会得到一条非常易读的错误消息,指向此行并指向试图实例化它的代码.
template< class T >
void marshal(std::string name, T *value)
{
static_assert(std::is_pod<T>::value && !std::is_pod<T>::value, "You cannot marshal a pointer.");
}
Run Code Online (Sandbox Code Playgroud)
问题是这段代码充其量是丑陋的.它看起来像一个黑客.我担心下次更改优化级别,升级编译器,打喷嚏等时,编译器会意识到第二种情况与第一种情况相同,它们都会停止工作.
有没有更好的方法来做我想做的事情?
这是一些背景.我想有几个不同版本的marshal(),它们适用于不同的输入类型.我想要一个使用模板作为默认情况的版本.我想要另一个特别禁止除char*之外的任何指针.
void marshal(std::string name, std::string)
{
std::cout<<name<<" is a std::string type."<<std::endl;
}
void marshal(std::string name, char *string)
{
marshal(name, std::string(string));
}
void marshal(std::string name, char const *string)
{
marshal(name, std::string(string));
}
template< class T >
void marshal(std::string name, T …Run Code Online (Sandbox Code Playgroud) 我正在尝试比较constexpr-if语句中的函数参数.
这是一个简单的例子:
constexpr bool test_int(const int i) {
if constexpr(i == 5) { return true; }
else { return false; }
}
Run Code Online (Sandbox Code Playgroud)
但是,当我用GCC 7使用以下标志编译它时:
g++-7 -std=c++1z test.cpp -o test
我收到以下错误消息:
test.cpp: In function 'constexpr bool test_int(int)':
test.cpp:3:21: error: 'i' is not a constant expression
if constexpr(i == 5) { return true; }
Run Code Online (Sandbox Code Playgroud)
但是,如果我test_int用不同的功能替换:
constexpr bool test_int_no_if(const int i) { return (i == 5); }
Run Code Online (Sandbox Code Playgroud)
然后以下代码编译没有错误:
int main() {
constexpr int i = 5;
static_assert(test_int_no_if(i));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我不明白为什么constexpr-if版本无法编译,特别是因为static_assert工作正常. …
我需要一种方法来验证常量字符串在编译时不包含某个字符.我想过使用static_assert,但是碰到了一堵砖墙,因为我正在尝试使用.find方法,它不是常量.
我可以选择在类的构造函数中进行检查(实例是static const所述类的成员).
但是在咬住子弹之前(因为改变构造函数的行为还有其他含义),我想看看是否还有其他人有一个创造性的开箱即用的想法仍然可以完成,最好是在编译时.
例如.我有CHARCOUNT(x)扩展到的宏sizeof(x)/sizeof(x[0]).我想static_assert用来确保每个宏扩展检查结果是否大于2,以避免有人传入指向字符串的指针而不是指向字符数组的指针.
我想要像这样的静态断言:
static_assert(x) > 2
Run Code Online (Sandbox Code Playgroud)
此宏将用于确保字符串副本不超过缓冲区大小,例如:
TCHAR szMyStr[10];
_tcscpy_s(szMyStr, CHARCOUNT(szMyStr), L"My result");
Run Code Online (Sandbox Code Playgroud)
如果有人意外地传入一个指针,其中CHARCOUNT将导致指向字符串的指针的长度,而不是我希望在编译时断言的字节数.
const TCHAR* myChars = L"My result";
auto len = CHARCOUNT(myChars);
Run Code Online (Sandbox Code Playgroud)
在CHARCOUNT上述应导致编译时断言.任何指针都会有所帮助.
static-assert ×10
c++ ×7
c++11 ×7
compile-time ×2
templates ×2
assertions ×1
c++14 ×1
c++17 ×1
constexpr ×1
if-constexpr ×1
iterator ×1
macros ×1
sfinae ×1
type-traits ×1