Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Work around incomplete type in static assert

Is there a way to static_assert inside a class when the expression depends on the class type itself? Maybe delay the evaluation until the type is complete or after template instantiation?

Example code:

#include <type_traits>

template<typename T>
struct Test {
   T x = 0; // make non-trivial
   static_assert(std::is_trivial<Test<T>>::value, "");
};

int main() {
    // would like static assert failure, instead get 'incomplete type' error
    Test<int> test1;
    Test<float> test2;
    return 0;
}
like image 409
Giovanni Funchal Avatar asked Mar 14 '17 06:03

Giovanni Funchal


2 Answers

Here's a solution using a helper class and a type alias for indirection. I believe this has no drawbacks.

template<typename T>
struct TestImpl {
    T x = 0; // make non-trivial
};

template<typename T>
struct TestHelper {
    using type = TestImpl<T>;
    static_assert(std::is_trivial<type>::value, "");
};

template<typename T>
using Test = typename TestHelper<T>::type;

edit: Alternatively TestHelper can be moved into TestImpl:

template<typename T>
struct TestImpl {
    T x = 0; // make non-trivial

    struct Helper {
        using type = TestImpl;
        static_assert(std::is_trivial<type>::value, "");
    };
};

template<typename T>
using Test = typename TestImpl<T>::Helper::type;
like image 87
Giovanni Funchal Avatar answered Sep 29 '22 01:09

Giovanni Funchal


I was also looking for a solution with static_assert, but constraints work too:

#include <type_traits>

namespace Private {
template<typename T>
struct Test {
   T x = 0;
};
}

template<typename T>
requires std::is_trivial<Private::Test<T>>::value
using Test = Private::Test<T>;

int main() {
    Test<int> test1;
    Test<float> test2;
    return 0;
}
like image 29
Cevik Avatar answered Sep 29 '22 01:09

Cevik