static assert that template typename T is NOT complete?

后端 未结 2 1342
你的背包
你的背包 2020-12-31 16:47

Is there a way to static_assert that a type T is Not complete at that point in a header? The idea is to have a compile error if someone adds #includes down

相关标签:
2条回答
  • 2020-12-31 17:04

    Here is a function using expression SFINAE based on chris proposal which allows checking whether a type is complete yet.
    My adoption needs no includes, errors-out when the required argument is missing (hiding the argument was not possible) and is suitable for C++11 onward.

    template<typename T>
    constexpr auto is_complete(int=0) -> decltype(!sizeof(T)) {
        return true;   
    }
    
    template<typename T>
    constexpr bool is_complete(...) {return false;}
    

    And a test-suite:

    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);
    }
    

    Output:

    1
    0
    1
    

    See live on coliru

    0 讨论(0)
  • 2020-12-31 17:21

    Passing a reference through ... doesn't work.

    5.2.2/7:

    When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the argument by invoking va_arg (18.10). [note skipped — n.m.] The lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are performed on the argument expression. An argument that has (possibly cv-qualified) type std::nullptr_t is converted to type void* (4.10). After these conversions, if the argument does not have arithmetic, enumeration, pointer, pointer to member, or class type, the program is ill-formed.

    Here's a kind-of-working solution hastily adapted from @chris's comment:

    #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!");
    
    0 讨论(0)
提交回复
热议问题