I've recently come across an interesting implementation of the SFINAE idiom and I'm having trouble working with the specialization classes. Let me explain with a simplified example. I'm utilizing 4 classes in my main function below-- 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;
}
Output:
Mr. Robert: Hello World!
Mr. Roboto: Konnichiwa Sekkai!
Variant_
is a template class and derives from Base
, which is an abstract class. English
and Japanese
are specialization classes and don't derive from anything.
Base:
class Base
{
public:
Base(){}
virtual ~Base(){}
protected:
virtual void dispatch_say_hi()=0;
};
Variant_:
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>());
}
};
Ok, I lied. There is a fifth class has_f
. It's a helper class to identify whether or not a function has been defined in the specializations. That's not where I'm having problems, but I've provided it just so this example can be compiled and run.
English:
class English
{
public:
void say_hi(){
std::cout<<"Hello World!"<< std::endl;
}
};
Japanese:
class Japanese
{
public:
void say_hi(){
std::cout<<"Konnichiwa Sekkai!"<<std::endl;
}
};
This all compiles and runs.
Here's my question:
Lets say I modify Japanese
.
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;
}
};
Now, when I try to run main()
, I get a segmentation fault at MrRoboto.dispatch_say_hi()
. It doesn't matter if the member variable is private or public, or if it is an int or string. I get a segmentation fault whenever I try to access any member variables. Why does this happen?
It's interesting to note that if I define another function, I can call it like so:
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";
}
};
The output of this is:
Mr. Robert: Hello World!
Mr. Roboto: Konnichiwa Sekkai! bleep bloop
Any ideas?