static断言模板typename T不完整?

时间:2014-09-11 20:12:58

标签: c++ templates static-assert incomplete-type

有没有办法在标题中的那一点上使用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类型”的错误,哦。有没有办法断言否定?

2 个答案:

答案 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

See live on coliru

答案 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!");