编辑:对我的问题的简短回答是,我对 SFINAE 可以做什么有一个错误的看法,它根本不检查函数体:sfinae 是否实例化了函数体?
我有一个类似的问题:是否可以编写模板来检查函数的存在?
不同的是,我不仅想检查函数是否存在,还想知道它是否真的会通过 SFINAE。这是我要完成的示例:
struct A
{
void FuncA() { std::cout << "A::FuncA" << std::endl; }
};
struct B
{
void FuncA() { std::cout << "B::FuncA" << std::endl; }
void FuncB() { std::cout << "B::FuncB" << std::endl; }
};
template<typename T>
struct Inter
{
void FuncA() { t.FuncA(); }
void FuncB() { t.FuncB(); }
T t;
};
// Always takes some sort of Inter<T>.
template<typename InterType>
struct Final
{
void CallFuncs()
{
// if( t.FuncA() exists and can be called )
t.FuncA();
// if( t.FuncB() exists and can be called )
t.FuncB();
}
InterType t;
};
void DoEverything()
{
Final<Inter<A>> finalA;
Final<Inter<B>> finalB;
finalA.CallFuncs();
finalB.CallFuncs();
}
请注意,在 CallFuncs() 中,FuncA() 和 FuncB() 将始终存在,但根据 Inter 中使用的类型 T,它们可能无法编译。当我尝试在上面链接的问题中使用答案时,它似乎总是给我真实的,我猜是因为它只是检查函数是否存在,而不是它实际上可以编译(尽管我不能排除我没有搞砸什么...)
为了有条件地调用我认为我可以使用 enable_if 的函数:
template<typename InterType>
typename std::enable_if< ! /* how to determine if FuncA can be called? */>::type TryCallFuncA( InterType& i )
{
}
template<typename InterType>
typename std::enable_if</* how to determine if FuncA can be called? */>::type TryCallFuncA( InterType& i )
{
i.FuncA();
}
template<typename InterType>
typename std::enable_if< ! /* how to determine if FuncB can be called? */>::type TryCallFuncB( InterType& i )
{
}
template<typename InterType>
typename std::enable_if</* how to determine if FuncB can be called? */>::type TryCallFuncB( InterType& i )
{
i.FuncB();
}
template<typename InterType>
struct Final
{
void CallFuncs()
{
TryCallFuncA(t);
TryCallFuncB(t);
}
InterType t;
};
但我不确定是否有任何方法可以将布尔值传递给 enable_if。有什么办法可以做到这一点,还是我需要回退到某种手动维护的类型特征来指示函数是否存在?
就可用的 C++11 功能集而言,我使用的是 MSVC 2010。
编辑:添加一个重要说明,在我的实际情况下,在我需要确定 Inter::FuncA/FuncB 是否会编译的地方,类 Inter 的实现实际上是不透明的,所以我不能只是冒泡孩子类型并检查它们上是否存在函数。