gpt4 book ai didi

c++ - 引用具有与模板不兼容的模板参数的 C++ 模板类型是否安全?

转载 作者:太空狗 更新时间:2023-10-29 22:54:27 25 4
gpt4 key购买 nike

在下面的代码示例中,我定义了一个类 DT(我的默认类型),我希望它能够作为任意模板的参数传递。在此示例中,我将 DT 作为 std::map 的键和值参数传递。我实际上从来没有尝试实例化 map ,我只是想使用 map 作为模板化函数(在本示例中为函数 f())的模板参数,该函数从未实际引用过类型——它仅用于生成特定于类型的函数实例。 (请注意,您实际上无法实例化 std::map ,因为映射的键必须是可比较的,但 DT 不是。)

#include <iostream>
#include <map>

using namespace std;

class DT {};

template <typename T>
string f() {
return "foo";
}

int main() {
cout << f<map<DT,DT>>() << endl;
return 0;
}

这似乎使用 g++ 工作正常。我什至尝试为所有四个映射参数传递 DT(覆盖默认比较器和分配器类型)。仍然有效。但我担心这种技术可能会因其他模板或其他编译器而失败。所以我的问题是:对于任何符合 c++11 标准(以及更高版本标准)的 c++ 编译器上的任何模板,这是否总是安全的。换句话说,只要您从不尝试实例化该模板,将完全不兼容的类型作为参数传递给模板是否总是安全的?

如果您想知道我到底为什么要做这样的事情,我正在尝试设置一个类,我可以在其中存储依赖于类型的配置字符串。它将有这两个方法:

template<typename T>
const string& get<T>() const;

template<typename T>
void set<T>(const string& value);

我的工作基本上令我满意。它有几个不错的功能。例如,类型 int、const int、int&、const int& 等都被视为同一类型(这正是我想要的)。如果没有找到更具体的派生类型的条目,您可以存储基类的配置字符串,稍后派生类型可以检索该配置字符串。但是对于 std::map 的情况,我希望能够使用类型 map 存储默认配置字符串,稍后将作为任何 map 的匹配项返回当手头没有找到特定 map 类型的条目时。如果上面的代码有效,那么我想我可以产生所需的行为。

最佳答案

不幸的是,我相信标准并不能保证 std::map<DT, DT>不会被实例化。 [temp.inst]/1仅指定

Unless a class template specialization has been explicitly instantiated or explicitly specialized, the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program. […]

请注意,这仅告诉我们何时保证模板被实例化,它并不能保证如果不需要这样的实例化,模板将不会被实例化。 [temp.inst]/10只为

[…] a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement ([stmt.if]), unless such instantiation is required. […]

请注意此列表中没有类模板。因此,我相信,理论上允许编译器实例化 std::map<DT, DT>。甚至认为没有必要这样做。如果实例化模板 std::mapDT由于键和值类型无效,因此您会遇到问题。我找不到关于实例化 std::map 的任何保证使用不支持比较运算符的键类型。虽然我希望这基本上适用于任何实现,但我确实认为理论上允许实现,例如,有一个 static_assert。检查 key 类型是否满足必要的要求。 [res.on.functions]/1似乎适用(强调我的):

In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on the implementation.

因此,我认为严格来说,标准并不能保证使用std::map<DT, DT>。将工作...

如果您只想使用 std::map<DT, DT>作为一种表示特殊情况的标记类型,我建议不要使用 std::map但是还有别的,例如:

template <typename, typename>
struct default_config_tag;

然后 default_config_tag<DT, DT>或者只是 DT作为你的标签(不确定你是否需要参数是具有两个类型参数的模板的实例)应该足够了......

关于c++ - 引用具有与模板不兼容的模板参数的 C++ 模板类型是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55888570/

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