Tob*_*lus 5 c++ gcc sfinae c++17
我尝试检测一个类是否已在 C++ 中实现。该类要么仅在之前声明过(情况 1),要么已实现(情况 2)。为了检测类的实现,SFINAE 表达式应该评估sizeof(T)
模板参数,如果类不完整,则模板参数将失败。
#include <type_traits>
// 1. Feature not supported: Class only declared
class Test;
// 2. Feature supported: Class implemented
// class Test {};
// Detection if class is complete
template<class T, class Enable = void>
struct is_complete
{
static constexpr bool value = false;
};
template<class T>
struct is_complete<T, std::enable_if_t<(sizeof(T) == sizeof(T))>>
{
static constexpr bool value = true;
};
int main(void)
{
if constexpr (is_complete<Test>::value)
{
// static_assert(is_complete<Test>::value, "Test is not complete");
return 1;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
问题是 main 方法中 consexpr if 条件的主体是在编译时计算的,即使它在运行时没有使用(程序在执行时返回 0)。如果我static_assert
在正文中包含 a ,则会产生以下错误消息:
<source>:20:9: error: static_assert failed due to requirement 'is_complete<Test, void>::value' "Test is not complete"
static_assert(is_complete<Test>::value, "Test is not complete");
^ ~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
Compiler returned: 1
Run Code Online (Sandbox Code Playgroud)
因此,这is_complete<Test>::value
似乎在 if 条件体内评估为 false,而 if 条件内的相同表达式在编译期间评估为 true,但在运行时则不会。我可以在 GCC 11.2 和 CLANG 12.0.1 中重现此行为。
我也尝试更改sizeof(T) == sizeof(T)
为sizeof(T) > 0
相同的结果。
如果我尝试实例化该类,然后将其转换为它的基类,我可以观察到相同的行为,如以下代码所示:
<source>:20:9: error: static_assert failed due to requirement 'is_complete<Test, void>::value' "Test is not complete"
static_assert(is_complete<Test>::value, "Test is not complete");
^ ~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
Compiler returned: 1
Run Code Online (Sandbox Code Playgroud)
然后编译器会抱怨 的强制转换unique_ptr
,如果该类已实现,则该强制转换有效:
<source>: In function 'std::unique_ptr<Base> Build()':
<source>:33:38: error: could not convert 'make_unique<Test>()' from 'unique_ptr<Test,default_delete<Test>>' to 'unique_ptr<Base,default_delete<Base>>'
33 | return std::make_unique<Test>();
| ~~~~~~~~~~~~~~~~~~~~~~^~
| |
| unique_ptr<Test,default_delete<Test>>
Compiler returned: 1
Run Code Online (Sandbox Code Playgroud)
所以我现在的问题是:
归档时间: |
|
查看次数: |
171 次 |
最近记录: |