鉴于:
struct A
{
virtual bool what() = 0;
};
template<typename T, typename Q>
struct B : public A
{
virtual bool what();
};
我想部分专业化
what
,例如:
template<typename T, typename Q>
bool B<T, Q>::what()
{
return true;
}
template<typename Q>
bool B<float, Q>::what()
{
return false;
}
但看来这是不可能的(是在C++11中吗?)所以我尝试了SFINAE:
template<typename T>
typename std::enable_if<std::is_same<T, float>::value, bool>::type B<T>::what()
{
return true;
}
template<typename T>
typename std::enable_if<!std::is_same<T, float>::value, bool>::type B<T>::what()
{
return false;
}
这也不起作用,但我不知道为什么,有人知道吗?所以我找到了这个线程并最终得到:
template<typename T, typename Q>
struct B : public A
{
virtual bool what()
{
return whatimpl(std::is_same<T, float>());
}
bool whatimpl(std::false_type)
{
return false;
}
bool whatimpl(std::true_type)
{
return true;
}
};
这个最终解决方案有效,但为什么
enable_if
技术不起作用?我也非常愿意接受我还没有遇到过的更清晰答案的建议。
我尽可能简化了我的示例 - 在我的实际用例中
what()
不被称为 what 并且实际上做了相当多的工作,并且我想“专门化”用户定义的类型,而不是float
。
标准仅明确允许类模板使用部分特化(请参阅 14.5.5 类模板部分特化)
对于类模板的成员,仅允许显式专业化。
14.7 (3) 说:
可以为函数模板、类模板、类成员声明显式特化 template 或会员模板。 template<> 引入了显式的专业化声明。
所以任何以开头的定义
template<typename T>
不是类模板专业化成员允许的语法。
[编辑]
对于 SFINAE 尝试,它失败了,因为实际上这里既没有重载也没有特化(SFINAE 在定义一组用于重载解析的候选函数或选择适当的特化时工作)。 What() 被声明为类模板的单个方法,并且应该具有单个定义,并且该定义应该具有以下形式:
template<typename T, typename Q>
B<T,Q>:: bool what(){...}
或者也可以明确专门用于 B 类的特定实例化:
template<>
B<SomeParticularTypeT,SomeParticularTypeTypeQ>:: bool what(){...}
任何其他形式在语法上都是无效的,因此 SFINAE 无法提供帮助。
template<typename T, typename Q>
struct B : public A
{
bool what()
{
return false; //Or whatever the default is...
}
};
template<typename Q>
struct B<float, Q> : public A
{
bool what()
{
return true;
}
};
#include <iostream>
using namespace std;
struct A
{
virtual bool what() = 0;
};
template <typename T, typename Q>
static bool what()
{
cout << "T: " << typeid (T).name() << " Q: " << typeid (Q).name() << endl;
return sizeof (T) < sizeof (Q);
}
template <typename Q>
static bool what(float t, Q q)
{
cout << "T: " << t << " Q: " << q << endl;
}
template<typename T, typename Q>
struct B : public A
{
virtual bool what()
{
return ::what<T, Q>();
}
};
int main()
{
B<int, char> bic;
B<float, char> bfc;
cout << bic.what() << endl;
cout << bfc.what() << endl;
return 0;
}