gpt4 book ai didi

c++ - 基于函数指针的简单 std::any 实现

转载 作者:行者123 更新时间:2023-12-03 10:04:39 24 4
gpt4 key购买 nike

我已阅读答案 to this question ,查看 std::any 的 gcc 实现,并不太了解实现。不过,我想尝试一下使用函数指针来推导类型的想法。
在调试中,我得到了预期的结果,但在发布时,我的模板特化被优化掉了......我尝试使用 #pragma optimize("", off)__declspec(noinline)但它没有帮助。
AFAIK 比较指向函数的指针不是 UB。所以我猜 MSVC(就我而言)优化了模板特化......
有没有办法使这项工作?

#include <iostream>
#include <memory>

template <typename T>
void deduce_type()
{}


class any
{
/*
template <typename T, typename ... Args>
any(Args&& ... args)
: ptr_(new T(std::forward<Args>(args) ...), std::default_delete<T>())
{}
*/

public:

template <typename T>
any(T&& other)
: ptr_(new T(std::forward<T>(other))),
deduce_type_(&deduce_type<T>)
{}

template <typename T>
bool contains_type() const
{
return deduce_type_ == &deduce_type<T>;
}

private:
// std::unique_ptr<void, std::default_delete<void>> ptr_;
void* ptr_;
void(*deduce_type_)();

};

struct Foo
{

};


int main()
{

any anyInt = 16;
any anyInt2 = 17;
any anyDouble = 2.0;
any anyFoo = Foo();


bool isInt = anyInt.contains_type<int>(),
isInt2 = anyInt2.contains_type<int>(),
notDouble = anyInt.contains_type<double>(), // 0 expected
isDouble = anyDouble.contains_type<double>(),
isFoo = anyFoo.contains_type<Foo>(),
notFoo = anyInt.contains_type<Foo>(); // 0 expected

std::cout << "is int = " << isInt << std::endl;
std::cout << "is int = " << isInt2 << std::endl;
std::cout << "is not double = " << notDouble << std::endl;
std::cout << "is double = " << isDouble << std::endl;
std::cout << "is Foo = " << isFoo << std::endl;
std::cout << "is not Foo = " << notFoo << std::endl;

return 0;
}

释放输出:
is int = 1
is int = 1
is not double = 1
is double = 1
is Foo = 1
is not Foo = 1
foo is deducible = 1
调试和预期输出:
is int = 1
is int = 1
is not double = 0
is double = 1
is Foo = 1
is not Foo = 0
foo is deducible = 1

所以根据评论,问题是由 Identical Code Folding 时的链接器引起的已启用(默认在 MSVC 的 Release 中)。我发现没有办法在代码中为单独的函数禁用这个链接器标志,所以除了发明一些丑陋的解决方法来防止函数被折叠到一个地址之外别无他法。那是通过强制他们以某种方式为每个模板实例化生成“唯一”指令......
当我将模板函数的签名更改为简单地返回一个整数时,我会得到所需的结果,但只有在明确提供了特定的特化...
template <typename T>
size_t deduce_type()
{
return 0;
}

template <>
size_t deduce_type<double>()
{
return 1;
}

template <>
size_t deduce_type<Foo>()
{
return 2;
}

在这种情况下,即使在不同的特化中返回相同的值,我也会得到预期的输出。然而,这仅在特化返回与基本模板不同的值时才成立。
我想我必须打开另一个问题......

最佳答案

您可以使用 解决此不符合项。变量 模板(或静态局部变量——在这种情况下你在构造函数中调用函数——或类模板的静态数据成员):

template<class T>
constexpr decltype(nullptr) tag{};

class any {
void *p;
const decltype(nullptr) *t;

public:
template<class T>
any(…) : p(…),t(&tag<T>) {}

// contains_type much as before
};
这当然基本上是 std::type_info ,但如果不需要该设施的其他功能,则可能更可取。

关于c++ - 基于函数指针的简单 std::any 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65811832/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com