【发布时间】:2018-11-29 11:38:52
【问题描述】:
简短的一般性问题:
有没有办法提供函数模板的默认“回退”重载?我在 Stack Overflow 上阅读了一些技术,但其中一个需要使用可变参数函数 (f(...)),这在我的情况下有一些严重的缺点,而其他需要列出所有重载的类型组合,这太冗长且不自动化足以满足我的需要。有人问过这个问题,但现在已经有几年了,所以我想知道是否有一些新的解决方案可以使用最新标准的功能,甚至可能有一些在 C++20 中使用概念可以实现的解决方案。
详细的问题:
我正在尝试在 C++ 中实现动态类型。关键是,我有几个“抽象”类型,如Bool、Integer、Decimal、String 等,它们用一些内置类型表示,即Integer 存储为long long , 但除bool 之外的任何整数类型都会转换为它。
现在我开始实现运算符。我可以手动实现所有可能的重载(即Bool + Integer,Integer + Integer,...),但我希望每个“类别”只有一个实现,即Decimal + any_lower_type_than<Decimal> (commutative),其中any_lower_type_than<Integer> 指的是某些层次结构的抽象类型。我有所有需要的元功能来区分实现的类别和层次结构。然后我将 SFINAE 与这些元函数一起使用来提供定义。例如:
// decimal + lower, commutative:
template <typename first_t, typename second_t,
std::enable_if_t<commutative_with_lower<first_t, second_t, Decimal>::value>* = nullptr>
Decimal operator+ (const first_t& first, const second_t& second) {
return first + second;
}
// string * lower than integer, commutative:
template <typename first_t, typename second_t,
std::enable_if_t<commutative_with_lower_than<first_t, second_t, String, Integer>::value>* = nullptr>
String operator* (const first_t& first, const second_t& second) {
String string_arg = is_string<first_t>::value ? first : second;
auto other_arg = is_string<first_t>::value ? second : first;
String result = "";
for (decltype(other_arg) i = 0; i < other_arg; ++i)
result += string_arg;
return result;
}
所以没关系,但我现在需要的是一些默认的“后备”实现,当找不到匹配项时,它会作为最后的手段被调用。所以我需要以某种方式强制回退实现成为最糟糕的匹配,但同时要匹配任何情况。
我读到可变参数函数“sinkhole”比任何东西都差。因此,自然的方法是提供作为operator+ (...) 的回退,这当然是不可能的。所以我将所有运算符更改为常规函数,例如operator_add 然后通过调用适当的operator_add 重载在更高级别实现operator+ 本身,其中默认重载实现为可变参数函数operator_add(...)。但后来我遇到了另一个问题。可变参数函数只接受平凡的类型。但我也需要将这种技术用于用户定义的类型。
所以问题是:对于可变参数函数 sinkhole,是否有任何替代技术可以确保最差的匹配?有没有办法在不修改函数参数的情况下做到这一点,也许通过修改模板参数,以便我可以在具有固定函数参数签名的实际运算符上使用该技术?
【问题讨论】:
-
我认为你想用传入的 Concept 创建重载。
标签: c++ templates overloading