重载模板函数的声明顺序
Overloaded templated function declaration order
我有一些代码,读起来像这样:
#include <map>
#include <string>
#include <functional>
using std::map;
using std::string;
using std::function;
using std::forward;
template<typename ToType, typename... FromTypes>
ToType construct(FromTypes&&... fromTypes) {
return ToType(forward<FromTypes>(fromTypes)...);
}
class Variant {
public:
map<string, Variant> toMap() const;
};
map<string, Variant> Variant::toMap() const {
return {
{"test", {}},
{"test1", {}},
};
}
// #1
template <typename MapType>
MapType variantToMap(Variant const& v) {
// I expect an error on the following line because it's referencing the function labeled #4 which has not been declared yet.
return variantToMap<MapType>(v, construct<typename MapType::key_type, string>, construct<typename MapType::mapped_type, Variant>);
}
// #2
template <typename MapType>
MapType variantToMap(Variant const& v, function<typename MapType::key_type(string)> const& keyConvert) {
// I expect an error on the following line because it's referencing the function labeled #4 which has not been declared yet.
return variantToMap<MapType>(v, keyConvert, construct<typename MapType::mapped_type, Variant>);
}
// #3
template <typename MapType>
MapType variantToMap(Variant const& v, function<typename MapType::mapped_type(Variant)> const& valueConvert) {
// I expect an error on the following line because it's referencing the function labeled #4 which has not been declared yet.
return variantToMap<MapType>(v, construct<typename MapType::key_type, string>, valueConvert);
}
// #4
template <typename MapType>
MapType variantToMap(Variant const& v, function<typename MapType::key_type(string)> const& keyConvert, function<typename MapType::mapped_type(Variant)> const& valueConvert) {
MapType res;
for (auto pair : v.toMap()) {
res[keyConvert(pair.first)] = valueConvert(pair.second);
}
return res;
}
int main() {
Variant a;
// #1
variantToMap<map<string, Variant>>(a);
// #2
{
int counter = 0;
variantToMap<map<int, Variant>>(a, [&counter](string) -> int { return ++counter; });
}
// #3
variantToMap<map<string, int>>(a, [](Variant) -> int { return 42; });
// #4
{
int counter = 0;
variantToMap<map<int, int>>(a, [&counter](string) -> int { return ++counter; }, [](Variant) -> int { return 42; });
}
return 0;
}
编译和工作正常。
然而,因为它被声明为无序的,我希望它会抛出错误。我认为原因是这些函数都是模板化的。然而,这对我来说仍然有点困惑,因为(例如)在varianttomap# 1中对varianttomap# 4的调用有3个参数,这意味着
是Clang和GCC不适当地接受这些函数,还是这是允许的?如果允许,理由是什么?
应该注意的是,我已经重新排序了这些函数,我只是好奇为什么它在第一个地方工作。
c++使用两阶段名称查找来解析模板定义中的标识符。(除非您有MSVC,它只使用第二阶段)。
当声明/定义模板时,所有不依赖于模板参数的名称都将被解析。当它被实例化时,依赖于模板参数的名称将被解析。这一次,在实例化点可见的名称参与其中,并且可以在查找过程中找到。
在你的例子中,内部的variantToMap
调用依赖于模板参数,所以在调用外部函数之前它们不会被解析。此时,所有4个变量都是可见的,并且可以找到。
相关文章:
- 按顺序声明的字符数组重叠
- 为什么结构属性声明和初始化顺序的行为是这样的?
- 类之外的 C++ 是保证为构造顺序的可变声明的顺序
- 重载函数声明的顺序在 c++ 中重要吗?
- C :使用声明和指令的顺序会影响选择
- 分割错误取决于我在C 中声明的顺序
- 当指定初始化程序的顺序和字段声明不一致时,clang可以删除函数调用
- Boost MPL-按顺序声明每种类型的类
- 如何按行主要顺序声明 3DArray
- 更改声明顺序时输出不正确
- GCC 警告初始化顺序与声明顺序不匹配
- 我们可以在 C 或 C++ 中打乱声明顺序吗?
- 如何根据方法实现的声明顺序对其进行排序
- 成员声明顺序在类中如果彼此依赖,则为最优解
- 重载模板函数的声明顺序
- 为什么初始化列表顺序必须与成员声明顺序匹配
- c++声明顺序(const/type/function)
- c++:函数重载和声明顺序的混淆
- 指向成员对象的成员指针和声明顺序
- c++指针声明顺序输出分段错误或总线错误