C++ SFINAE使用模板、专门化和实现类型擦除
我最近遇到了一个有趣的SFINAE习语实现,我在使用专门化类时遇到了问题。让我用一个简单的例子来解释。我在下面的主函数中使用了4个类--C++ SFINAE使用模板、专门化和实现类型擦除,c++,segmentation-fault,sfinae,specialization,C++,Segmentation Fault,Sfinae,Specialization,我最近遇到了一个有趣的SFINAE习语实现,我在使用专门化类时遇到了问题。让我用一个简单的例子来解释。我在下面的主函数中使用了4个类--Base,Variant,English,Japanese #include <iostream> #include <memory> int main() { Variant_<English> MrRobert; Variant_<Japanese> MrRoboto; std::c
Base
,Variant
,English
,Japanese
#include <iostream>
#include <memory>
int main() {
Variant_<English> MrRobert;
Variant_<Japanese> MrRoboto;
std::cout << "Mr. Robert: ";
MrRobert.dispatch_say_hi();
std::cout << "Mr. Roboto: ";
MrRoboto.dispatch_say_hi();
return 0;
}
class Japanese
{
private:
std::string something_else;
public:
void say_hi(){
std::cout<<"Konnichiwa Sekkai!";
something_else = " bleep bloop"; //segfault!
std::cout<<something_else<<std::endl;
}
};
Variant\uu
是一个模板类,它派生自Base
,后者是一个抽象类<代码>英语和日语
都是专业化课程,没有任何来源
基础:
Mr. Robert: Hello World!
Mr. Roboto: Konnichiwa Sekkai!
class Base
{
public:
Base(){}
virtual ~Base(){}
protected:
virtual void dispatch_say_hi()=0;
};
template<class T>
struct has_f
{
typedef char yes;
typedef char (&no)[2];
template<class U>
static yes test_say_hi(__typeof__(&U::say_hi));
template<class U>
static no test_say_hi(...);
static const int say_hi = sizeof(test_say_hi<T>(0)) == sizeof(yes);
};
template<class Impl>
class Variant_: private Base
{
std::unique_ptr<Impl> impl_;
public:
template<int I> struct int_{};
typedef int_<0> not_implemented;
typedef int_<1> implemented;
void say_hi(not_implemented){
std::cout << "..." << std::endl;
}
void say_hi(implemented){
impl_->say_hi();
}
void dispatch_say_hi(){
say_hi(int_<has_f<Impl>::say_hi>());
}
};
class English
{
public:
void say_hi(){
std::cout<<"Hello World!"<< std::endl;
}
};
class Japanese
{
public:
void say_hi(){
std::cout<<"Konnichiwa Sekkai!"<<std::endl;
}
};
变体:
Mr. Robert: Hello World!
Mr. Roboto: Konnichiwa Sekkai!
class Base
{
public:
Base(){}
virtual ~Base(){}
protected:
virtual void dispatch_say_hi()=0;
};
template<class T>
struct has_f
{
typedef char yes;
typedef char (&no)[2];
template<class U>
static yes test_say_hi(__typeof__(&U::say_hi));
template<class U>
static no test_say_hi(...);
static const int say_hi = sizeof(test_say_hi<T>(0)) == sizeof(yes);
};
template<class Impl>
class Variant_: private Base
{
std::unique_ptr<Impl> impl_;
public:
template<int I> struct int_{};
typedef int_<0> not_implemented;
typedef int_<1> implemented;
void say_hi(not_implemented){
std::cout << "..." << std::endl;
}
void say_hi(implemented){
impl_->say_hi();
}
void dispatch_say_hi(){
say_hi(int_<has_f<Impl>::say_hi>());
}
};
class English
{
public:
void say_hi(){
std::cout<<"Hello World!"<< std::endl;
}
};
class Japanese
{
public:
void say_hi(){
std::cout<<"Konnichiwa Sekkai!"<<std::endl;
}
};
日语:
Mr. Robert: Hello World!
Mr. Roboto: Konnichiwa Sekkai!
class Base
{
public:
Base(){}
virtual ~Base(){}
protected:
virtual void dispatch_say_hi()=0;
};
template<class T>
struct has_f
{
typedef char yes;
typedef char (&no)[2];
template<class U>
static yes test_say_hi(__typeof__(&U::say_hi));
template<class U>
static no test_say_hi(...);
static const int say_hi = sizeof(test_say_hi<T>(0)) == sizeof(yes);
};
template<class Impl>
class Variant_: private Base
{
std::unique_ptr<Impl> impl_;
public:
template<int I> struct int_{};
typedef int_<0> not_implemented;
typedef int_<1> implemented;
void say_hi(not_implemented){
std::cout << "..." << std::endl;
}
void say_hi(implemented){
impl_->say_hi();
}
void dispatch_say_hi(){
say_hi(int_<has_f<Impl>::say_hi>());
}
};
class English
{
public:
void say_hi(){
std::cout<<"Hello World!"<< std::endl;
}
};
class Japanese
{
public:
void say_hi(){
std::cout<<"Konnichiwa Sekkai!"<<std::endl;
}
};
现在,当我尝试运行main()
时,我在MrRoboto.dispatch\u say\u hi()
上遇到了一个分段错误。成员变量是私有的还是公共的,或者是int或string,都无关紧要。每当我试图访问任何成员变量时,就会出现分段错误。为什么会发生这种情况
有趣的是,如果我定义了另一个函数,我可以这样调用它:
class Japanese
{
public:
void say_hi(){
std::cout<<"Konnichiwa Sekkai!";
say_something_else();
std::cout<<std::endl;
}
void say_something_else()
{
std::cout<<" bleep bloop";
}
};
有什么想法吗?您有一个从未设置过的
唯一的\u ptr
,因此它保持初始默认值,即nullptr
。它以前工作过,因为除了函数之外,您不是来自日语的任何东西(注意:您有取消引用空指针的未定义行为,即使在您的情况下,大多数实现都可以工作)
请注意,您所做的被称为“策略模式”。它有时非常有用,也可能很有趣,但是请注意,这种模式的最大缺点是缺乏界面-没有任何东西可以告诉用户要实现什么函数,因此他们必须查看代码。您有一个从未设置的唯一\u ptr
,因此它保持在初始默认值,这是nullptr
。它以前工作过,因为除了函数之外,您不是来自日语的任何东西(注意:您有取消引用空指针的未定义行为,即使在您的情况下,大多数实现都可以工作)
请注意,您所做的被称为“策略模式”。它有时非常有用,也可能很有趣,但是请注意,这种模式的最大缺点是缺乏界面-没有任何东西可以告诉用户要实现什么函数,因此他们必须查看代码。您有一个从未设置的唯一\u ptr
,因此它保持在初始默认值,这是nullptr
。它以前工作过,因为除了函数之外,您不是来自日语的任何东西(注意:您有取消引用空指针的未定义行为,即使在您的情况下,大多数实现都可以工作)
请注意,您所做的被称为“策略模式”。它有时非常有用,也可能很有趣,但是请注意,这种模式的最大缺点是缺乏界面-没有任何东西可以告诉用户要实现什么函数,因此他们必须查看代码。您有一个从未设置的唯一\u ptr
,因此它保持在初始默认值,这是nullptr
。它以前工作过,因为除了函数之外,您不是来自日语的任何东西(注意:您有取消引用空指针的未定义行为,即使在您的情况下,大多数实现都可以工作)
请注意,您所做的被称为“策略模式”。它有时非常有用,也可能很有趣,但是请注意,这种模式的最大缺点是缺乏界面-没有任何东西可以告诉用户要实现什么功能,因此,他们必须查看代码。我确信std::unique\u ptr impl\u
没有初始化我确信std::unique\u ptr impl\u
没有初始化我确信std::unique\u ptr impl\u
没有初始化我确信std::unique\u ptr impl\u
没有初始化就是这样。一旦我从Variant
初始化了impl
,它就按预期工作了。感谢您命名的模式!我得好好读一读,就是这样。一旦我从Variant
初始化了impl
,它就按预期工作了。感谢您命名的模式!我得好好读一读,就是这样。一旦我从Variant
初始化了impl
,它就按预期工作了。感谢您命名的模式!我得好好读一读,就是这样。一旦我从Variant
初始化了impl
,它就按预期工作了。感谢您命名的模式!我得仔细阅读一下。