Mar*_*ata 4 virtual sfinae c++11
下面的代码virtual A::foo()用B::foo() override. 如果BROKEN没有定义,那么它编译就好了。我对std::enable<std::is_pod<Q>::value>::type恶作剧的理解是它有效地替换了 SFINAE 表达式void,这应该与普通的void.
但是,它不会编译。我收到编译器错误:
$ make a CXXFLAGS="-std=c++11 -DBROKEN"
icpc -std=c++11 -DBROKEN a.cpp -o a
a.cpp(24): error: object of abstract class type "B<int>" is not allowed:
pure virtual function "A::foo" has no overrider
B<int> b;
^
Run Code Online (Sandbox Code Playgroud)
$ make a CXXFLAGS="-std=c++11 -DBROKEN" CXX=g++
g++ -std=c++11 -DBROKEN a.cpp -o a
a.cpp: In function ‘int main()’:
a.cpp:24:11: error: cannot declare variable ‘b’ to be of abstract type ‘B<int>’
B<int> b;
^
a.cpp:9:7: note: because the following virtual functions are pure within ‘B<int>’:
class B : A
^
a.cpp:5:16: note: virtual void A::foo()
virtual void foo() = 0;
^
make: *** [a] Error 1
Run Code Online (Sandbox Code Playgroud)
这是测试用例:
#include <type_traits>
class A {
public:
virtual void foo() = 0;
};
template<typename T>
class B : A
{
public:
#ifdef BROKEN
template<class Q = T>
typename std::enable_if<true>::type
#else
void
#endif
foo() override { }
};
int main()
{
B<int> b;
b.foo();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果我不使用虚函数,std::enable<true>事情就会按预期工作。
这些结果适用于 gcc 4.8.3。使用 gcc 5.3,我得到了一行额外的编译器错误:
a.cpp:19:9: error: member template ‘std::enable_if<true>::type B<T>::foo()’ may not have virt-specifiers
foo() override { }
^
Run Code Online (Sandbox Code Playgroud)
为什么不?
这不是很好,但它完成了工作......使用 SFINAE 条件编译的虚拟覆盖。它有更多的调用开销(foo()call foo_x()),但也许编译器会优化它。
#include <type_traits>
class A {
public:
virtual void foo() = 0;
};
template<typename T>
class B : A
{
public:
template<class Q = T>
typename std::enable_if<true>::type
foo_x() { }
void foo() override { foo_x(); }
};
int main()
{
B<int> b;
b.foo(); // not an example of polymorphism! just want it to compile.
return 0;
}
Run Code Online (Sandbox Code Playgroud)
那个例子只是为了证明它可以编译并且没有用。的实际实现foo_x将有多个实现:
template<class Q = T>
typename std::enable_if<is_pod<Q>::value>::type
foo_x() { /* do something with POD */}
template<class Q = T>
typename std::enable_if<std::is_base_of<std::string,Q>::value>::type
foo_x() { /* do something with a std::string */}
template<class Q = T>
typename std::enable_if<std::is_base_of<MyCrazyClass,Q>::value>::type
foo_x() { /* do something with a derived class of MyCrazyClass */}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1900 次 |
| 最近记录: |