提出的问题: Type condition in template
非常相似,但最初的问题还没有得到很好的解答。
#include "stdafx.h"
#include <type_traits>
class AA {
public:
double a;
double Plus(AA &b) {
return a + b.a;
}
};
template<class T> double doit(T &t) {
if (std::is_same<T, AA>::value)
return t.Plus(t);
else
return t + t;
}
int _tmain(int argc, _TCHAR* argv[])
{
double a;
AA aa;
doit(a);
doit(aa);
return 0;
}
这不编译,我也没想到。这样的事情可能吗?基于模板值,我希望编译一些代码,而不是其他代码。在这里,&#39; double&#39;没有一个名为&#34; Plus&#34;的方法。和班级&#34; AA&#34;不会覆盖&#39; +&#39;运营商。在考虑操作的细微语义时,操作符重载并不总是令人满意的,因此我正在寻找替代方法。我更喜欢做#ifdef(真正的条件编译,如参考问题所示),但是基于模板值。
答案 0 :(得分:3)
重载?
template<class T>
double doit(T &t) {
return t + t;
}
double doit(AA &t) {
return t.Plus(t);
}
明确的专业化也是可能的,虽然多余:
template<class T>
double doit(T &t) {
return t + t;
}
template<>
double doit<>(AA &t) {
return t.Plus(t);
}
答案 1 :(得分:2)
double doit(AA &t) {
return t.Plus(t);;
}
template<class T> double doit(T &t) {
return t + t;
}
您的代码无效,因为如果模板推断为AA
,那么正文中的t + t
格式不正确。另一方面,如果T
被推断为double
,那么t.Plus(t)
就会变得格格不入。
为了更好地了解发生的事情: 为每个模板类型实例化一个模板,使用。
doIt(a)
使用doIt
实例化T = double
:
double doIt<double>(double &t) {
if (false)
return t.Plus(t); // <-- syntax error
else
return t + t;
}
doIt(aa)
使用doIt
实例化T = AA
:
double doIt<AA>(AA &t) {
if (true)
return t.Plus(t);
else
return t + t; // <-- syntax error
}
您应避免专门化功能模板,因为功能过载。你可以阅读这篇优秀的Herb Sutter文章:Why Not Specialize Function Templates?
答案 2 :(得分:2)
你想要的是静态的if。 C ++没有它。有很多方法可以解决它,没有一个像本机支持一样好。除了其他两个答案中指定的方法之外,您还可以尝试标记调度。
template<class T> double doitImpl(T &t, std::true_type) {
return t.Plus(t);
}
template<class T> double doitImpl(T &t, std::false_type) {
return t+t;
}
template<class T> double doit(T &t) {
return doitImpl(t, std::is_same<T, AA>);
}
答案 3 :(得分:2)
从C ++ 17开始,如果调用if-constexpr,则会出现静态。以下编译好,因为clang-3.9.1和gcc-7.1.0,最新的MSVC编译器19.11.25506也可以使用选项/ std:c ++ 17处理得很好。
template<class T> double doit(T &t) {
if constexpr (std::is_same_v<T, AA>)
return t.Plus(t);
else
return t + t;
}
答案 4 :(得分:0)
此代码编译并运行:
#include <boost/type_traits/is_floating_point.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/utility/enable_if.hpp>
using namespace boost;
class AA {
public:
double a;
AA Plus(AA &b) {
AA _a;
_a.a = a + b.a;
return _a;
}
};
template<class T>
typename disable_if<is_floating_point<T>, T >::type
doit(T &t) {
return t.Plus(t);
}
template<class T>
typename enable_if<is_floating_point<T>, T >::type
doit(T &t) {
return t+t;
}
int _tmain(int argc, _TCHAR* argv[])
{
double a;
AA aa;
doit(a);
doit(aa);
return 0;
}