my_fun可以如使用SFINAE以下来实现。
namespace details{
struct A{};
struct B:A{};
// A container will have a begin and an end. Also make it first prerference
template<typename T>
auto my_fun_impl(T const & obj, B *) -> decltype(obj.begin(),obj.end(),void())
{
std::cout<<"Container\n";
}
// Default choice
template<typename T>
auto my_fun_impl(T const & obj,A*) -> void
{
std::cout<<"Other than Container\n";
}
}
template<typename T>
auto my_fun(T const & obj) -> void
{
details::my_fun_impl(obj,static_cast<details::B *>(0));
}
注意这里传递一个Base
或Derived
类指针,否则编译器会抱怨不明确的功能定义。
编译器将尝试匹配my_fun_impl
的确切签名与B pointer
,它将在容器的情况下成功。因为一个容器将有begin()和end(),预计在尾随返回类型中。
在非容器类型的情况下,第一选项将不匹配。而且我们知道一个Base
类指针可以容纳派生类对象,所以默认匹配会成功。
及后续测试代码的输出
int main()
{
my_fun(std::vector<int>{1,2,3});
my_fun(1);
}
将
Container
Other than Container
Demo on coliru
除了看起来像一个糟糕的设计,我建议你看一下在设计相反,你可以使用[ *型性状*](http://en.cppreference.com/w/cpp/types#Type_traits_.28since_C.2B.2B11.29)。您可能需要实现适合您的特定类型特征,例如'is_container'。 –
'std :: string'当然是一个字符的容器,所以这个问题假设了一个错误的二分法。 – MSalters