有没有办法在标题中的那一点上使用static_assert类型T 不完成?如果有人在他们不应该的地方添加#includes,那么这个想法就是编译错误。
相关:How to write `is_complete` template?
使用该链接的答案,
namespace
{
template<class T, int discriminator>
struct is_complete {
static T & getT();
static char (& pass(T))[2];
static char pass(...);
static const bool value = sizeof(pass(getT()))==2;
};
}
#define IS_COMPLETE(X) is_complete<X,__COUNTER__>::value
class GType;
static_assert(!IS_COMPLETE(GType),"no cheating!");
不幸的是,这给出了“无效使用incomlete类型”的错误,哦。有没有办法断言否定?
答案 0 :(得分:4)
这是一个使用基于chris proposal的表达式SFINAE的函数,它允许检查类型是否完整。
我的采用不需要包含,当缺少必需的参数时出错(隐藏参数是不可能的),并且适用于C ++ 11以后。
template<typename T>
constexpr auto is_complete(int=0) -> decltype(!sizeof(T)) {
return true;
}
template<typename T>
constexpr bool is_complete(...) {return false;}
还有一个测试套件:
struct S;
bool xyz() {return is_complete<S>(0);}
struct S{};
#include <iostream>
int main() {
std::cout << is_complete<int>(0) << '\n';
std::cout << xyz() << '\n';
std::cout << is_complete<S>(0);
}
输出:
1
0
1
答案 1 :(得分:2)
通过...
传递引用不起作用。
5.2.2 / 7:
当给定参数没有参数时,参数以接收方式传递 function可以通过调用
va_arg
来获取参数的值(18.10)。 [注意跳过 - n.m.]左值到右值(4.1),数组到指针(4.2),以及 函数到指针(4.3)对参数表达式执行标准转换。一个论点 has(可能cv
- 限定)类型std::nullptr_t
转换为类型void*
(4.10)。完成这些转换后, 如果参数没有算术,枚举,指针,成员指针或类类型,则 节目形成不良。
这是一种从@ chris的评论中匆匆改编的一种工作解决方案:
#include <iostream>
#include <utility>
namespace
{
template<typename T, int>
constexpr auto is_complete(int) -> decltype(sizeof(T),bool{}) {
return true;
}
template<typename T, int>
constexpr auto is_complete(...) -> bool {
return false;
}
}
#define IS_COMPLETE(T) is_complete<T,__LINE__>(0) // or use __COUNTER__ if supported
struct S;
static_assert(IS_COMPLETE(int), "oops 1!");
static_assert(!IS_COMPLETE(S), "oops 2!");
struct S {};
static_assert(IS_COMPLETE(S), "oops 3!");