微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

传递指针参数时意外的模板实例化

如何解决传递指针参数时意外的模板实例化

以下代码无法编译(在 godbolt.org 上使用 MSVC 19.28 和 /std:c++latest 以及 Clang 12.0 和 -std=c++20 进行测试):

#include <variant>

struct some_thing;
using var = std::variant<some_thing>;

// There should be NO need to instantiate the template here,right?
void take(var* v) {}

int main() {
    var* v = nullptr;
    take(v); // This is the offending line - tries to instantiate the variant template and fails as 'some_thing' is undefined up until Now.
    return 0;
}

在 main 中的调用如何需要模板实例化?我们只是传递一个指针。这是一个错误还是我遗漏了什么?

Template instantiation 如果使用模板的指针类型(就像我正在做的那样)而不是当 typedef'ing 它作为 typedef 不引入新类型(即模板的实例)时不应该发生.我可能仍然缺少一些东西,但这应该使我的示例代码能够编译。

请参阅下面的 MSVC 错误消息。请注意,此问题不是关于理解错误消息。它是关于为什么甚至首先发生模板实例化。

C:/data/msvc/14.28.29333/include\type_traits(807): error C2139: 'some_thing': an undefined class is not allowed as an argument to compiler intrinsic type trait '__is_trivially_destructible'
<source>(3): note: see declaration of 'some_thing'
C:/data/msvc/14.28.29333/include\variant(956): note: see reference to class template instantiation 'std::is_trivially_destructible<some_thing>' being compiled
C:/data/msvc/14.28.29333/include\variant(956): note: see reference to variable template 'const bool conjunction_v<std::is_trivially_destructible<some_thing> >' being compiled
C:/data/msvc/14.28.29333/include\variant(1014): note: see reference to alias template instantiation 'std::_Variant_destroy_layer<some_thing>' being compiled
<source>(11): note: see reference to class template instantiation 'std::variant<some_thing>' being compiled
C:/data/msvc/14.28.29333/include\type_traits(661): error C2139: 'some_thing': an undefined class is not allowed as an argument to compiler intrinsic type trait '__is_constructible'
<source>(3): note: see declaration of 'some_thing'
C:/data/msvc/14.28.29333/include\xsmf_control.h(61): note: see reference to class template instantiation 'std::is_move_constructible<some_thing>' being compiled
C:/data/msvc/14.28.29333/include\xsmf_control.h(62): note: see reference to variable template 'const bool conjunction_v<std::is_move_constructible<some_thing>,std::negation<std::conjunction<std::is_trivially_move_constructible<some_thing> > > >' being compiled
C:/data/msvc/14.28.29333/include\xsmf_control.h(100): note: see reference to alias template instantiation 'std::_SMF_control_move<std::_Variant_destroy_layer_<some_thing>,some_thing>' being compiled
C:/data/msvc/14.28.29333/include\xsmf_control.h(139): note: see reference to alias template instantiation 'std::_SMF_control_copy_assign<std::_Variant_destroy_layer_<some_thing>,some_thing>' being compiled
C:/data/msvc/14.28.29333/include\xsmf_control.h(146): note: see reference to alias template instantiation 'std::_SMF_control_move_assign<std::_Variant_destroy_layer_<some_thing>,some_thing>' being compiled
C:/data/msvc/14.28.29333/include\variant(1014): note: see reference to alias template instantiation 'std::_SMF_control<std::_Variant_destroy_layer_<some_thing>,some_thing>' being compiled
C:/data/msvc/14.28.29333/include\type_traits(630): error C2139: 'some_thing': an undefined class is not allowed as an argument to compiler intrinsic type trait '__is_constructible'
<source>(3): note: see declaration of 'some_thing'
C:/data/msvc/14.28.29333/include\xsmf_control.h(39): note: see reference to class template instantiation 'std::is_copy_constructible<some_thing>' being compiled
C:/data/msvc/14.28.29333/include\xsmf_control.h(40): note: see reference to variable template 'const bool conjunction_v<std::is_copy_constructible<some_thing>,std::negation<std::conjunction<std::is_trivially_copy_constructible<some_thing> > > >' being compiled
C:/data/msvc/14.28.29333/include\xsmf_control.h(63): note: see reference to alias template instantiation 'std::_SMF_control_copy<std::_Variant_destroy_layer_<some_thing>,some_thing>' being compiled
C:/data/msvc/14.28.29333/include\variant(491): error C2079: 'std::_Variant_storage_<false,some_thing>::_Head' uses undefined struct 'some_thing'
C:/data/msvc/14.28.29333/include\variant(838): note: see reference to class template instantiation 'std::_Variant_storage_<false,some_thing>' being compiled
C:/data/msvc/14.28.29333/include\variant(941): note: see reference to class template instantiation 'std::_Variant_base<some_thing>' being compiled
C:/data/msvc/14.28.29333/include\xsmf_control.h(85): note: see reference to class template instantiation 'std::_Variant_destroy_layer_<some_thing>' being compiled
C:/data/msvc/14.28.29333/include\xsmf_control.h(124): note: see reference to class template instantiation 'std::_Deleted_copy_assign<std::_Variant_destroy_layer_<some_thing>,some_thing>' being compiled
C:/data/msvc/14.28.29333/include\variant(1014): note: see reference to class template instantiation 'std::_Deleted_move_assign<std::_Variant_destroy_layer_<some_thing>,some_thing>' being compiled
C:/data/msvc/14.28.29333/include\type_traits(730): error C2139: 'some_thing': an undefined class is not allowed as an argument to compiler intrinsic type trait '__is_destructible'
<source>(3): note: see declaration of 'some_thing'
C:/data/msvc/14.28.29333/include\variant(1016): note: see reference to class template instantiation 'std::is_destructible<some_thing>' being compiled
C:/data/msvc/14.28.29333/include\variant(1016): note: see reference to variable template 'const bool conjunction_v<std::is_object<some_thing>,std::negation<std::is_array<some_thing> >,std::is_destructible<some_thing> >' being compiled
C:/data/msvc/14.28.29333/include\variant(1016): error C2338: variant<Types...> requires all of the Types to meet the Cpp17Destructible requirements N4828 [variant.variant]/2.
Compiler returned: 2

解决方法

您的问题与ADL有关。

来自链接:

否则,对于函数调用表达式中的每个参数,都会检查其类型以确定它将添加到查找中的关联命名空间和类集。

检查将导致函数调用中使用的模板的实例化,如果在这种情况下 std::variant 需要 some_thing 的类型定义,这将失败。

我们知道 ADL 是问题所在,在这种情况下,如果我们知道不想在其他命名空间或作用域中查找为该类型定义的函数 take(),我们可以简单地抑制 ADL std::variant<some_thing> 使用 :: operator

如果您通过将格式错误的行替换为 ::take(v); 来更改代码,您的代码将编译,因为 ADL 将不再发生。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。