问题
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;
}
回答1:
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;
回答2:
You can define a destructor and put the static_assert there, at least with g++ 5.4 -std=c++11 this works.
回答3:
(moving from the comments)
You can add an intermediate class to keep the logic, and let your clients instantiate a derived one, which just contains the static_assert
s
#include <type_traits>
template<typename T>
struct TestImpl {
T x = 0; // make non-trivial
};
template<typename T>
struct Test : TestImpl<T> {
static_assert(std::is_trivial<TestImpl<T>>::value, "");
using TestImpl<T>::TestImpl; // inherit constructors
};
来源:https://stackoverflow.com/questions/42779120/work-around-incomplete-type-in-static-assert