我一直在尝试实现类似于static_assertC++ 11标准中定义的方法.主要问题是C++编译器如何将传递给的文本消息static_assert写成const char*?我可以让编译器写一个像这样的消息A_is_not_POD.这就是我所拥有的:
#define MY_STATIC_ASSERT(condition, name) \
typedef char name[(condition) ? 1 : -1];
Run Code Online (Sandbox Code Playgroud)
但是让编译器编写类似"Error: A is not POD."Any建议的东西会很好吗?
请考虑以下代码:
template <unsigned int N>
struct myclass
{
unsigned int f() {return N;}
unsigned int g() {static_assert(N > 0, ""); return N-1;}
};
Run Code Online (Sandbox Code Playgroud)
问题:我是否保证以下代码将编译:
myclass<0> c;
c.f();
Run Code Online (Sandbox Code Playgroud)
但以下不会:
myclass<0> c;
c.f();
c.g();
Run Code Online (Sandbox Code Playgroud) #include <cstddef>
template<typename... Types>
constexpr std::size_t getArgCount(Types&&...) noexcept
{
return sizeof...(Types);
}
struct A
{
int n;
void f()
{
static_assert(getArgCount(n) > 0); // not ok, why?
}
};
int main()
{
int n;
static_assert(getArgCount(n) > 0); // ok
}
Run Code Online (Sandbox Code Playgroud)
为什么在编译时无法获得模板函数的参数计数?
错误信息:
1>test.cpp
1>test.cpp(17,45): error C2131: expression did not evaluate to a constant
1>test.cpp(17,42): message : failure was caused by a read of a variable outside its lifetime
1>test.cpp(17,42): message : see usage of 'this'
Run Code Online (Sandbox Code Playgroud) 假设我有一个模板函数,它接受一个整数和一个const引用到类型为T的实例.现在,根据整数,只有一些T是可加入的,否则在运行时抛出异常.
如果此函数的所有使用都使用常量整数,则可以使int成为模板参数并使用静态断言来检查它是否可接受.因此,func(1,c)不会使用func<1>(c)并将获得编译时类型检查.有没有办法编写func(1,c)并仍然保持编译时检查,同时还能够编写func(i,c)和使用动态断言?目标是使其对开发人员透明.添加这种安全性而不打扰开发人员关于编译时常量之类的东西会很棒.他们可能只记得func(1,c)总是有效并且使用它,避免检查.
如何尽可能使用静态断言定义函数,否则动态断言?
以下代码显示了Ivan Shcherbakov的 GCC解决方案:
#include <iostream>
#include <cassert>
template<typename T>
void __attribute__((always_inline)) func(const int& i, const T& t);
void compile_time_error_() __attribute__((__error__ ("assertion failed")));
template<>
void __attribute__((always_inline))
func(const int& i, const float& t)
{
do {
if (i != 0) {
if (__builtin_constant_p(i)) compile_time_error_();
std::cerr << "assertion xzy failed" << std::endl;
exit(1);
}
} while (0);
func_impl<float>(i,t);
}
Run Code Online (Sandbox Code Playgroud)
这只允许i = 0和T = float的组合.对于其他组合,一个好方法是创建一个宏,生成代码为template<> func(const int& i, const …
这是我正在尝试做的简化版本
enum First
{
a,
b,
c,
nbElementFirstEnum,
};
enum Second
{
a,
b,
c,
nbElementSecondEnum,
};
static_assert(
First::nbElementFirstEnum == Second::nbElementSecondEnum,
"Not the same number of element in the enums.");
/*static_assert(
First::nbElementFirstEnum == Second::nbElementSecondEnum,
"Not the same number of element in the enums." + First::nbElementFirstEnum + " " + Second::nbElementSecondEnum);*/
Run Code Online (Sandbox Code Playgroud)
但是我希望能够在断言消息中打印First :: nbElementFirstEnum和Second :: nbElementSecondEnum的值(就像在注释版本中显然不起作用).我尝试使用"#"进行宏连接.我还尝试使用可变参数模板,使用%10检索每个数字并将"0"字符添加到检索到的值,但我得到的只是constexpr char [].
所以我的问题是如何让我的枚举值以字符串文字打印.
可能重复:
最有趣的话题是: 在编译时打印sizeof(T) 但是我不希望有警告或退出代码来知道值.
c ++概念中有什么新东西?根据我的理解,它们在功能上等同于使用static_assert,但是以"漂亮"的方式意味着编译器错误将更具可读性(因为Bjarne Stroustup说你不会得到10页或错误,而只是一个).
基本上,您可以使用概念实现的一切都是真的static_assert吗?
有什么我想念的吗?
我有以下方案:
struct Baz {};
struct Qux {};
struct Base {
virtual ~Base() {}
virtual void foo() = 0;
};
template<typename T> struct Identity { static bool const value = false; };
template<typename T> void bar(T) { static_assert(Identity<T>::value, "Busted!!!"); }
template<> void bar<Baz>(Baz) {}
template<typename T>
struct Derived : Base {
T m;
void foo() { bar(m); }
};
int main() {
Base *b0 = new Derived<Baz>;
b0->foo();
Base *b1 = new Derived<Qux>;
(void) b1;
}
Run Code Online (Sandbox Code Playgroud)
也就是说,我有一个纯虚拟类Base和一个模板类Derived,它根据需要继承 …
假设我已经在Haskell中编写了一个函数,并且想断言它是尾递归的,并且编译器会对其进行优化。有办法吗?
我知道有一种方法可以在Scala中使用@tailrec注释。
import scala.annotation.tailrec
class Factorial2 {
def factorial(n: Int): Int = {
@tailrec def factorialAcc(acc: Int, n: Int): Int = {
if (n <= 1) acc
else factorialAcc(n * acc, n - 1)
}
factorialAcc(1, n)
}
}
Run Code Online (Sandbox Code Playgroud) 考虑一下:
template <typename T>
struct hash
{
static_assert(false,"Not implemented.");
};
struct unhashable {};
template <typename T>
auto test(const T &t) -> decltype((*(hash<T> const *)nullptr)(t),int);
void test(...);
int main()
{
std::cout << std::is_same<decltype(test(std::declval<unhashable>())),void>::value;
}
Run Code Online (Sandbox Code Playgroud)
除了显然缺少标题,这应该编译吗?
换句话说,我问的是,如果在推断重载函数模板的返回值的同时触发尾随decltype内部的静态断言失败是否要求停止编译,或者是否只是丢弃了重载.
在gcc 4.7上,编译失败.我很积极,虽然这将在gcc 4.8中编译好(但在此刻无法检查).谁是对的?
我有一个包含多个函数对象的库,可能只接受几种类型std::is_integral.我想在条件失败时std::is_invocable返回false,但是static_assert当用户试图调用函数对象的实例时,我也想要一个很好的错误消息.这是我目前拥有的函数对象的简化示例:
struct function
{
template<typename Iterator>
auto operator()(Iterator first, Iterator last) const
-> std::enable_if_t<std::is_integral_v<
typename std::iterator_traits<Iterator>::value_type
>>
{ /* something */ }
};
Run Code Online (Sandbox Code Playgroud)
有了这样的实现,std::is_invocable是std::false_type在未满足条件SFINAE如预期,但用户遇到丑陋SFINAE错误消息,当他们试图调用与不符合条件SFINAE参数的函数对象.
为了获得更好的错误消息,我尝试了以下解决方案:
struct function
{
template<typename Iterator>
auto operator()(Iterator first, Iterator last) const
-> void
{
static_assert(std::is_integral_v<typename std::iterator_traits<Iterator>::value_type>,
"function can only be called with a collection of integers");
/* something */
}
};
Run Code Online (Sandbox Code Playgroud)
有了这个实施,得到用户当原始SFINAE条件不满足,但友好的错误消息std::is_invocable是std::true_type,当问是否function实例可以处理类型不满足std::is_integral.
我试了几个技巧和涉及的变化decltype(auto), …
static-assert ×10
c++ ×9
c++11 ×5
sfinae ×2
c++-concepts ×1
c++17 ×1
c99 ×1
class ×1
compile-time ×1
constexpr ×1
haskell ×1
inheritance ×1
integer ×1
macros ×1