检查是否定义了类型

xin*_*aiz 7 c++ templates type-traits incomplete-type

考虑这个例子:

#include <iostream>
#include <type_traits>

template <class, class = void>
struct is_defined : std::false_type
{ };

template <class T>
struct is_defined<T,
    std::enable_if_t<std::is_object<T>::value &&
                    !std::is_pointer<T>::value
        >
    > : std::true_type
{
private:
    static const T test; //try to create incomplete type member
};

struct defined { };

struct forward_declared;

int main()
{
    std::cout << std::boolalpha
              << is_defined<defined>::value << std::endl
              << is_defined<forward_declared>::value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

输出是true两者兼而有之.我想如果我尝试创建struct不完整类型的成员,那么这个模板特化将从重载集中丢弃.但事实并非如此.删除static const原因不完整类型的编译时错误.这种方法有什么问题,如果有可能,怎么能实现呢?

n. *_* m. 12

试试这个:

template <class T>
struct is_defined<T,
    std::enable_if_t<std::is_object<T>::value &&
                    !std::is_pointer<T>::value &&
                    (sizeof(T) > 0)
        >
    > : std::true_type
{
};
Run Code Online (Sandbox Code Playgroud)

  • **警告:此代码是错误的。**它仅告诉您该类型是否已定义*当“is_define”首次实例化时*。结果由编译器缓存,并且即使在定义类型之后也将保留其值。除非出于某种原因你想要这种行为,否则不要使用它![示例](https://gcc.godbolt.org/z/jqjbx6n33) (6认同)

sky*_*ack 5

通常,在这种情况下,您可以将一些不接受不完整类型的运算符用于sfinae表达式。
例如,您可以使用typeid

#include <iostream>
#include <type_traits>
#include <utility>

template<typename T, typename = void>
constexpr bool is_defined = false;

template<typename T>
constexpr bool is_defined<T, decltype(typeid(T), void())> = true;

struct defined { };
struct forward_declared;

int main()
{
    std::cout << std::boolalpha
              << is_defined<defined> << std::endl
              << is_defined<forward_declared> << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

正如其他人提到的,另一个有效的运算符是sizeof

  • **警告:此代码是错误的。**它仅告诉您该类型是否已定义*当“is_define”首次实例化时*。结果由编译器缓存,并且即使在定义类型之后也将保留其值。除非出于某种原因你想要这种行为,否则不要使用它![示例](https://gcc.godbolt.org/z/T8ez75sME) (4认同)