- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
在一个通用函数中,我使用以下成语,
template<class It1, class It2>
void do_something(It1 first, It1 second, It2 d_first){
... other stuff here...
using std::copy;
copy(first, second, d_first);
}
do_something
是一个通用函数,它不应该知道任何其他库的任何具体信息(可能除了 std::
)。 p>
现在假设我的命名空间 N
中有几个迭代器。
namespace N{
struct itA{using trait = void;};
struct itB{using trait = void;};
struct itC{using trait = void;};
}
我想在这个命名空间中为这些迭代器重载拷贝。我自然会这样做:
namespace N{
template<class SomeN1, class SomeN2>
SomeN2 copy(SomeN1 first, SomeN1 last, SomeN2 d_first){
std::cout << "here" << std::endl;
}
}
但是,当我使用 N::A
、N::B
或 N::C
调用 do_something
> 参数我得到“模棱两可的复制调用”,即使它们与 N::copy
位于相同的命名空间中。
有没有办法在上述原始函数的上下文中战胜std::copy
?
我认为如果我对模板参数施加约束,那么 N::copy
将是首选。
namespace N{
template<class SomeN1, class SomeN2, typename = typename SomeN1::trait>
SomeN2 copy(SomeN1 first, SomeN1 last, SomeN2 d_first){
std::cout << "here" << std::endl;
}
}
但这无济于事。
我可以尝试哪些其他变通方法让通用调用 copy 更喜欢参数命名空间中的拷贝而不是 std::copy
。
完整代码:
#include<iostream>
#include<algorithm>
namespace N{
struct A{};
struct B{};
struct C{};
}
namespace N{
template<class SomeN1, class SomeN2>
SomeN2 copy(SomeN1 first, SomeN1 last, SomeN2 d_first){
std::cout << "here" << std::endl;
}
}
template<class It1, class It2>
void do_something(It1 first, It1 second, It2 d_first){
using std::copy;
copy(first, second, d_first); // ambiguous call when It is from namespace N (both `std::copy` and `N::copy` could work.
}
int main(){
N::A a1, a2, a3;
do_something(a1, a2, a3);
}
一个典型的错误信息是
错误:重载‘copy(N::A&, N::A&, N::A&)’的调用不明确
我是否认为 C++ 概念会通过更喜欢具有更多约束而不是更少约束的函数调用来提供帮助?
最佳答案
您可以将 copy()
声明为 public friend function在您的迭代器类中。这有点像替代部分特化(这对函数来说是不可能的),因此重载决议会更喜欢它们,因为它们更特化:
#include <iostream>
#include <algorithm>
#include <vector>
namespace N
{
template<class SomeN1, class SomeN2>
SomeN2 copy(SomeN1 first, SomeN1 last, SomeN2 d_first)
{
std::cout << "here" << std::endl;
return d_first;
}
template <class T>
struct ItBase
{
template <class SomeN2>
friend SomeN2 copy(T first, T last, SomeN2 d_first)
{
return N::copy(first, last, d_first);
}
};
struct A : ItBase<A>{};
struct B : ItBase<B>{};
struct C : ItBase<C>{};
}
template<class It1, class It2>
void do_something(It1 first, It1 second, It2 d_first){
using std::copy;
copy(first, second, d_first);
}
int main(){
N::A a1, a2, a3;
std::cout << "do something in N:" << std::endl;
do_something(a1, a2, a3);
std::vector<int> v = {1,2,3};
std::vector<int> v2(3);
std::cout << "do something in std:" << std::endl;
do_something(std::begin(v), std::end(v), std::begin(v2));
for (int i : v2)
std::cout << i;
std::cout << std::endl;
}
见 this demo验证它是否有效。
我介绍了一个通用基类,它为所有迭代器声明必要的 friend 。因此,无需像您尝试的那样声明标签,您只需从 ItBase
继承即可。
注意:如果 N::copy()
应该仅与 N
中的这些迭代器一起使用,则可能不再需要它,因为这些友元函数将是公开的无论如何都在 N
中可见(就好像它们是自由函数一样)。
在评论中,有人建议,如果 N
中的迭代器无论如何都有一个公共(public)基类,则只需用这个基类声明 N::copy
,例如
namespace N
{
template <class SomeN2>
SomeN2 copy(ItBase first, ItBase last, SomeN2 d_first) { ... }
}
不幸的是,这会产生与期望相反的效果:std::copy
总是优于 N::copy
因为如果你传递一个A
,它必须被向下转换以匹配 N::copy
而 std::copy
不需要转换。 Here您可以看到显然 std::copy
被尝试调用(这会导致错误,因为 N::A
缺少一些类型定义)。
因此,您不能将通用基类用于 N::copy
的签名。我在解决方案中使用它的唯一原因是避免重复代码(必须在每个迭代器类中声明友元函数)。我的 ItBase
根本不参与重载决议。
但是请注意,如果您的迭代器碰巧有一些您想在 N::copy
的实现中使用的公共(public)成员(无论是否从某个公共(public)基类派生并不重要) ,你可以用我上面的解决方案来做到这一点:
namespace N
{
template <class T>
struct ItBase
{
template <class SomeN2>
friend SomeN2 copy(T first, T last, SomeN2 d_first)
{
first.some_member();
last.some_member();
return d_first;
}
};
struct A : ItBase<A>{ void some_member() {} };
struct B : ItBase<B>{ void some_member() {} };
struct C : ItBase<C>{ void some_member() {} };
}
见 here它是如何工作的。
在同一行中,如果 A、B、C 具有共同行为,则可以用以某种方式参数化的共同模板类替换它们。
namespace N
{
template <class T, int I>
struct ItCommon
{
...
};
using A = ItCommon<double,2>;
using B = ItCommon<int, 3>;
using C = ItCommon<char, 5>;
}
...
namespace N{
template<class T, int I, class Other>
SomeN2 copy(ItCommon<T, I> first, ItCommon<T, I> last, Other){
...
}
}
由于这个(非 friend )copy
函数肯定比 std::copy
更受限制,并且由于 ADL,当其中一个参数属于 N
命名空间。另外,作为非好友,这个 copy
函数是一个可选组件。
关于c++ - 如何编写具有高重载优先级的类标准函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54400763/
我最近在读 CSAPP。在 10.9 节中,它说标准 I/O 不应该与 socket 一起使用,原因如下: (1) The restrictions of standard I/O Restricti
似乎是一个足够标准的问题,可以保证解决方案中的标准设计: 假设我想在文件中写入 x+2(或更少)个字符串。 x 字符串构成一个部分的内容,这两个字符串构成该部分的页眉和页脚。要注意的是,如果内容中没有
代码版本管理 在项目中,代码的版本管理非常重要。每个需求版本的代码开发在版本控制里都应该经过以下几个步骤。 在master分支中拉取该需求版本的两个分支,一个feature分支,
我有以下sql查询,我需要获取相应的hibernate条件查询 SELECT COUNT(DISTINCT employee_id) FROM erp_hr_payment WHERE payment
所以我正在编写一些代码,并且最近遇到了实现一些 mixin 的需要。我的问题是,设计混音的正确方法是什么?我将使用下面的示例代码来说明我的确切查询。 class Projectile(Movable,
我的环境变量包含如下双引号: $echo $CONNECT_SASL_JAAS_CONFIG org.apache.kafka.common.security.plain.PlainLoginModu
示例: /** * This function will determine whether or not one string starts with another string. * @pa
有没有办法在 Grails 中做一个不区分大小写的 in 子句? 我有这个: "in"("name", filters.tags) 我希望它忽略大小写。我想我可以做一个 sqlRestriction
我搜索了很长时间,以查找将哪些boost库添加到std库中,但是我只找到了一个新库的完整列表(如此处:http://open-std.org/jtc1/sc22/wg21/docs/library_t
我已经通过使用这个肮脏的黑客解决了我的问题: ' Filter managerial functions ActiveSheet.Range("$A$1:$BW$2211").Auto
因此,我很难理解我需要遵循的标准,以便我的 Java 程序能够嵌入 HTML。我是否只需将我的主类扩展到 Applet 类,或者我还需要做更多的事情吗?另外,在我见过的每个 Applet 示例中,它都
我对在 Hibernate 中使用限制有疑问。 我必须创建条件,设置一些限制,然后选择日期字段最大值的记录: Criteria query = session.createCriteria(Stora
我有标准: ICriteria criteria = Session.CreateCriteria() .SetFetchMode("Entity1", FetchMo
我很难编写条件来选择所有子集合或孙集合为空的实体。我可以将这些作为单独的条件来执行,但我无法将其组合成一个条件。 类结构: public class Component { p
@Entity class A { @ManyToMany private List list; ... } @Entity class B { ... } 我想使用条件(不是 sql 查询)从 A
我的数据库中有以下表结构: Table A: Table B: Table C: _______________
请帮助我: 我有下一张 table : 单位 ID 姓名 用户 ID 姓名 利率 单位 ID 用户 ID 我不明白如何从 SQL 创建正确的条件结构: 代码: SELECT * FROM Unit W
我正在构建一个包含项目的网站,每个项目都有一个页面,例如: website.com/book/123 website.com/film/456 website.com/game/789 每个项目都可以
我需要使用两个属性的组合来过滤结果列表。一个简单的 SQL 语句如下所示: SELECT TOP 10 * FROM Person WHERE FirstName + ' ' + LastName L
我有一个“ super 实体”SuperEntity 和三个扩展父类(super class)的实体 ChildEntity1、...、ChildEntity3。 搜索数据库中的所有实体很容易,即我们
我是一名优秀的程序员,十分优秀!