可能之前有人问过,但这一切已经接近我对C++的理解和认知的极限,所以我在理解正在谈论的内容和到底发生了什么方面有点慢。让我直接跳到代码。这有效:
template <typename T>
class Foo
{
struct Bar
{
Bar() {}
~Bar() noexcept {}
Bar(Bar&& b) : Bar() { swap(*this, b); }
friend void swap(Bar& b1, Bar& b2) { /* ... */ }
};
};
template class Foo<int>; // explicit instantiation of Foo with int type
但是我该如何移动 swap 的定义呢?在Bar之外结构体?如果我这样做:
template <typename T>
class Foo {
struct Bar {
// ...
Bar(Bar&& b) : Bar() { swap(*this, b); } // line 16
// ...
template <typename V>
friend void swap(typename Foo<V>::Bar&, typename Foo<V>::Bar&);
};
};
template <typename T>
void swap(typename Foo<T>::Bar& b1, typename Foo<T>::Bar& b2) {} // line 26
template class Foo<int>; // line 31
g++(4.7.1,标志:-Wall -std=c++11)报告:
main.cpp: In instantiation of ‘Foo<T>::Bar::Bar(Foo<T>::Bar&&)
[with T = int; Foo<T>::Bar = Foo<int>::Bar]’:
main.cpp:31:16: required from here
main.cpp:16:28: error: no matching function for call to
‘swap(Foo<int>::Bar&, Foo<int>::Bar&)’
main.cpp:16:28: note: candidate is:
main.cpp:26:6: note: template<class T> void swap(typename Foo<T>::Bar&,
typename Foo<T>::Bar&)
main.cpp:26:6: note: template argument deduction/substitution failed:
main.cpp:16:28: note: couldn't deduce template parameter ‘T’
我猜 swap 的代码显式实例化时也需要创建 Foo ,这是有道理的,但为什么编译器不能弄清楚 swap(Foo<int>::Bar&...)需要创建?为什么模板替换失败?还是我都弄错了?
更新 1
与:
template <typename T> class Foo;
template <typename T>
void swap(typename Foo<T>::Bar& b1, typename Foo<T>::Bar& b2);
template <typename T>
class Foo {
struct Bar {
Bar(Bar&& b) : Bar() { swap(*this, b); } // line 19
friend void swap<>(Foo<T>::Bar& b1, Foo<T>::Bar& b2); // line 20
};
};
template <typename T>
void swap(typename Foo<T>::Bar& b1, typename Foo<T>::Bar& b2) {} // line 26
template class Foo<int>; // line 29
g++(4.7.1,标志:-Wall -std=c++11)报告:
main.cpp: In instantiation of ‘struct Foo<int>::Bar’:
main.cpp:29:16: required from here
main.cpp:20:17: error: template-id ‘swap<>’ for ‘void swap(Foo<int>::Bar&, Foo<int>::Bar&)’ does not match any template declaration
main.cpp: In instantiation of ‘Foo<T>::Bar::Bar(Foo<T>::Bar&&) [with T = int; Foo<T>::Bar = Foo<int>::Bar]’:
main.cpp:29:16: required from here
main.cpp:19:24: error: no matching function for call to ‘Foo<int>::Bar::Bar()’
main.cpp:19:24: note: candidate is:
main.cpp:19:5: note: Foo<T>::Bar::Bar(Foo<T>::Bar&&) [with T = int; Foo<T>::Bar = Foo<int>::Bar]
main.cpp:19:5: note: candidate expects 1 argument, 0 provided
main.cpp:19:28: error: no matching function for call to ‘swap(Foo<int>::Bar&, Foo<int>::Bar&)’
main.cpp:19:28: note: candidate is:
main.cpp:26:8: note: template<class T> void swap(typename Foo<T>::Bar&, typename Foo<T>::Bar&)
main.cpp:26:8: note: template argument deduction/substitution failed:
main.cpp:19:28: note: couldn't deduce template parameter ‘T’
更新 2
好的,所以这是不可能的。 Piotr 已链接到 Output a nested class inside a template ,但我不明白答案。为什么不能swap在其声明之外定义?据我(错误)理解,为什么编译器不能为 swap(Foo<int>::Bar&...) 创建代码并在代码中链接到它以显式实例化 Foo<int> ?我完全误解了发生了什么吗?有什么问题?
更新 3
好的,这不能完成,因为如果有模板特化,编译器不能保证调用swap。在 Foo 之外定义自 Foo<some_class>::Bar 以来是明确的在特定专业中可能是完全不同的东西。我希望我做对了。但是,为什么在我创建 Foo 的显式实例化之前 g++ 不警告我这一点? ?
template <typename T>
class Foo {
struct Bar {
// ...
Bar(Bar&& b) : Bar() { swap(*this, b); }
// ...
template <typename V>
friend void swap(typename Foo<V>::Bar&, typename Foo<V>::Bar&);
};
};
template <typename T>
void swap(typename Foo<T>::Bar& b1, typename Foo<T>::Bar& b2) {}
//template class Foo<int>; // let's comment this explicit instantiation out.
此代码编译良好(g++ 4.7.1,标志:-Wall -std=c++11)。但是,它不应该警告我这段代码可能会导致问题吗?当我添加 Foo 的显式实例化时,问题不在于该行本身,而在于 swap在 Foo 之外实现的代码.
最佳答案
问题不在于 friend .
问题出在这个函数本身:
template <typename T>
void swap(typename Foo<T>::Bar& b1, typename Foo<T>::Bar& b2) {} // line 26
推导模板参数T来自嵌套类是不可能的,请参阅:Output a nested class inside a template甚至更好的答案是:https://stackoverflow.com/a/4092248/1463922
举例说明为什么它不能完成,考虑这个函数:
template <class T>
void foo(typename A<T>::Bar);
还有这个 A 定义:
template <class T>
struct A { typedef int Bar; };
这个电话:
int a;
foo(a);
什么是 T在这个例子中?是int因为A<int>::Bar是int , 或 float因为
A<float>::Bar是int太或任何你想要的......问题是你正在调用什么功能foo<int>(int)或 foo<float>(int)或者……
或者举个更接近问题的例子:
template <class T>
struct Foo {
struct Bar {};
};
看来编译器在解决这个问题上应该没有问题:
template <class T>
void resolve(typename Foo<T>::Bar*);
但编译器即使在这里也有问题,因为它不确定某些其他类的特化是否不会使用其他类的内部结构,如下所示:
template <class T>
struct Foo<T*> {
typedef Foo<T>::Bar Bar;
};
因此:
Foo<void>::Bar b;
resolve(&b);
编译器没有机会知道调用哪个版本:
resolve<void>(Foo<void>::Bar*);
// or
resolve<void*>(Foo<void>::Bar*);
// ^
我能给你什么建议 - 使用内联 friend - 但用其他一些模板类来实现它。这行得通 - 但我确信这有点过度设计:
template <class S>
class ImplementSwap;
template <typename T>
class Foo {
public:
struct Bar {
int a;
Bar() {}
~Bar() {}
friend class ImplementSwap<Foo<T>>;
friend void swap(Foo<T>::Bar& b1, Foo<T>::Bar& b2)
{ ImplementSwap<Foo<T>>::doSwap(b1, b2); }
Bar(Bar&& b) { swap(*this, b); }
};
};
template <class T>
class ImplementSwap<Foo<T>> {
public:
static void doSwap(typename Foo<T>::Bar&,typename Foo<T>::Bar&);
};
template <class T>
void ImplementSwap<Foo<T>>::doSwap(typename Foo<T>::Bar&,typename Foo<T>::Bar&)
{
// this one is not inline....
}
我公开了 Bar 来做这个测试:
Foo<int>::Bar a = Foo<int>::Bar(); // move constructor
int main() {
swap(a,a); // explicit swap
}
<罢工> [老的] 我之前的回答是完全错误的,第一条评论引用它。 罢工>
<罢工>friend void swap<>(typename Foo<T>::Bar&, typename Foo<T>::Bar&);
// ^^
罢工><罢工>[/OLD] 罢工>
关于c++ - 如何显式实例化具有友元函数嵌套类的模板类 (C++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12875679/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/