template <size_t N>
class Foo
{
static_assert(N > 0, "WRONG");
//void Something() = 0; //my original implementation
};
int main() {
Foo<0> *p2 = nullptr; //no error
Foo<0> p; //gives an error
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我已分别测试了两条线.初始化p2时不调用static_assert但是它被调用并确实在p上失败.这是有意的吗?(我在gcc,clang和VC上尝试过)
解决方法有哪些?由于我正在使用抽象模板化类,如果断言仅在实例化非指针对象时执行,那将是一场噩梦.我可以使用工厂,但这不是一个合适的解决方案.
如何引入static_assert模板变量定义?
我的尝试是使用 lambda 函数:
#include <type_traits>
#include <utility>
#include <cstdlib>
namespace
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wglobal-constructors"
template< typename F >
F f = ([] () { static_assert(std::is_default_constructible< F >{}); }(), F{});
#pragma clang diagnostic pop
}
struct L
{
L() = default;
L(L const &) = delete;
L(L &&) = delete;
};
int
main()
{
static_cast< void >(f< L >);
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
但对于不可移动的对象,不可能以这种方式构造值对象。
使用逗号运算符我无法在 form 中执行值初始化F f = ([] () { …
我正在尝试编写一个函数,如果使用编译时常量参数调用它将触发编译时错误,如果参数的值与a不匹配static_assert,但仍然可以在运行时使用计算值调用.
有点像这样:
template<int N> void f(N){
static_assert(N == 5, "N can only be 5.");
do_something_with(N);
}
void f(int N){
if(N == 5){
do_something_with(N);
}
}
volatile int five = 5;
volatile int six = 6;
int main() {
f(5); //ok
f(6); //compile-time error
f(five); //ok
f(six); //run-time abort
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能做到这一点?
此外,如果可能的话,我希望能够保留简单的f(something)语法,因为此代码适用于不熟悉模板语法的初学者程序员可以使用的库.
我正在阅读《现代C ++设计》一书的第一章。特别是,编译时间断言。我的以下代码有问题:
template<bool> struct CompileTimeChecker
{
CompileTimeChecker(...) {}
};
template<> struct CompileTimeChecker<false> {};
#define STATIC_CHECK(expr, msg)\
{\
struct ERROR_##msg {ERROR_##msg() {}};\
CompileTimeChecker<((expr) != 0)>(ERROR_##msg());\
}
int main()
{
STATIC_CHECK(0, MessageNull);
STATIC_CHECK(1, MessageOne);
}
Run Code Online (Sandbox Code Playgroud)
对于g ++ 7.4.0和clang ++ 6.0.0,这不会引发编译时错误。但是,以下代码确实引发了错误(按预期):
template<bool> struct CompileTimeChecker
{
CompileTimeChecker(...) {}
};
template<> struct CompileTimeChecker<false> {};
#define STATIC_CHECK(expr, msg)\
{\
struct ERROR_##msg {ERROR_##msg(int i) {i;}};\
CompileTimeChecker<((expr) != 0)>(ERROR_##msg(0));\
}
int main()
{
STATIC_CHECK(0, MessageNull);
STATIC_CHECK(1, MessageOne);
}
Run Code Online (Sandbox Code Playgroud)
第二个代码的唯一区别是带有参数的构造函数的用法。
在两种情况下,预期的错误消息是:
no matching function for call to …我有一个性能关键代码,可以查询N个索引。如何static_assert在不牺牲性能的情况下检查是否给出了准确的N个索引?
#include <array>
template<int N>
void test(const std::array<int, N>& indices)
{
// static_assert: has three elements.
return;
}
int main()
{
test<3>({1, 2, 3}); // OK
test<3>({1, 2}); // Needs to crash, because 2 < 3
test<2>({1, 2, 3}); // Crashes, because 3 > 2
test<2>({1, 2}); // OK
return 0;
}
Run Code Online (Sandbox Code Playgroud) 在以下 C++20 函数模板中:
template<int i>
void f() {
if constexpr (i == 1)
g();
else if constexpr (i == 2)
h();
else
??? // <--error
}
Run Code Online (Sandbox Code Playgroud)
有什么我们可以写的东西,???这样f<3>()在编译时调用就会失败?
当尝试验证固定长度字符串数组在编译时是否已排序时,使用 时会出现奇怪的行为strncmp。
如果验证函数引用全局数组,则 N 的所有值似乎都有效。
#include <cstring>
#define N 8 // vary values of N
const char STRINGS[][N] = {"a", "b", "c"};
constexpr bool is_sorted_global() {
for (int i = 0; i < sizeof(STRINGS) / N - 1; i++) {
if (strncmp(STRINGS[i], STRINGS[i + 1], N) > 0) {
return false;
}
}
return true;
}
int main()
{
// always works for any N
static_assert(is_sorted_global(), "list is not sorted");
}
Run Code Online (Sandbox Code Playgroud)
但是,如果使用函数模板,则只有 N 小于或等于 8 的值才有效。
template<const char …Run Code Online (Sandbox Code Playgroud) 此代码无法编译,因为静态断言失败。
#include <vector>
#include <type_traits>
class A {
};
int main()
{
std::vector<A> v;
static_assert(std::is_trivially_copyable<decltype(v[0])>::value);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
另一方面,如果我将 替换decltype(v[0])为A,则它可以编译。问题在于v[0]是 的类型引用A而不是A. 我怎样才能让它v以某种方式工作?
这个问题关系到这一个除了不是处理类型名称的模板参数,我想使用一个枚举非类型模板参数.
是否有可能只有特化的模板化(类成员函数),在非类型模板参数的情况下没有通用(工作)定义?
通过在类体中声明并仅提供特化,我能够使一个版本工作,但是任何使用非定义模板参数的误操作都不会产生错误,直到链接.更糟糕的是,缺失的符号隐含地指的是枚举的整数值而不是它的名称,所以它会让其他开发人员感到困惑.
我能够BOOST_STATIC_ASSERT从引用的问题中获取技术仅适用于typename模板参数.
此代码演示了这个想法.我不希望CAT-version调用编译:
#include <iostream>
#include <boost/static_assert.hpp>
// CLASS HEADER FILE:
struct foo_class
{
enum AllowedTypes { DOG, CAT };
template <AllowedTypes type>
void add_one_third( double bar ) const
{
BOOST_STATIC_ASSERT_MSG(sizeof(type)==0, "enum type not supported.");
}
};
// CLASS SOURCE FILE
template<>
void foo_class::add_one_third<foo_class::DOG>( double bar ) const
{
std::cout << "DOG specialization: " << bar + 1./3. << std::endl;
}
// USER SOURCE FILE
int main()
{
std::cout << "Template Specialization!\n\n"; …Run Code Online (Sandbox Code Playgroud) 如果用户尝试使用给定的模板参数调用所述函数,那么如何在编译时专门化模板函数来生成错误?
通过使用以下习语,我能够为模板类获得此行为...
template <typename T>
class MyClass< std::vector<T> >;
Run Code Online (Sandbox Code Playgroud)
我试图修改的函数的基本签名是......
template <typename T>
T bar(const int arg) const {
...
}
Run Code Online (Sandbox Code Playgroud)
如果我使用与以前禁用某些模板类相同的范例......
template<>
std::string foo::bar(const int arg) const;
Run Code Online (Sandbox Code Playgroud)
我可以生成链接器错误,我认为这比运行时错误更令人满意,但仍然不是我正在寻找的.
因为我不能够使用C++ 11,我不能使用static_assert,如所描述这里.相反,我试图这样使用BOOST_STATIC_ASSERT......
template<>
std::string foo::bar(const int arg) const {
BOOST_STATIC_ASSERT(false);
return "";
}
Run Code Online (Sandbox Code Playgroud)
但是,这会产生以下编译时错误,即使我没有尝试使用我试图禁止的模板参数调用该函数的实例...
error: invalid application of 'sizeof' to incomplete type 'boost::STATIC_ASSERTION_FAILURE<false>'
Run Code Online (Sandbox Code Playgroud)
我找到了这篇文章,但它并没有真正提供我觉得适用于我的任何见解.有人可以帮忙吗?
c++ ×10
static-assert ×10
templates ×3
c++11 ×2
constexpr ×2
assertions ×1
boost ×1
c++14 ×1
c++20 ×1
c-strings ×1
enums ×1
if-constexpr ×1
overloading ×1
sorting ×1
stdarray ×1
type-traits ×1