提出的问题: 在模板中键入条件
非常相似,但原始问题并未得到完全回答。
#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;
}
Run Code Online (Sandbox Code Playgroud)
这不会编译,我也没有期望。这样的事情可能吗?基于模板值,我希望一些代码可以编译,而其他则不需要。在这里,“ double”没有称为“ Plus”的方法,而“ AA”类不会覆盖“ +”运算符。考虑操作的细微语义时,操作符重载并不总是可取的,因此我正在寻找一种替代方法。我宁愿进行#ifdef的工作(如参考问题中所述的进行真正的条件编译),但要基于模板值。
由于 C++17 有静态 if 被称为 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;
}
Run Code Online (Sandbox Code Playgroud)
你想要的是一个静态的 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>);
}
Run Code Online (Sandbox Code Playgroud)
double doit(AA &t) {
return t.Plus(t);;
}
template<class T> double doit(T &t) {
return t + t;
}
Run Code Online (Sandbox Code Playgroud)
您的代码不起作用,因为如果模板被推断为AA那么t + t体内的格式不正确。另一方面, ifT推导出 as doublethent.Plus(t)就变得格式错误。
为了更好地理解正在发生的事情:为调用的每个模板类型实例化一个模板。
doIt(a)实例doIt化为T = double:
double doIt<double>(double &t) {
if (false)
return t.Plus(t); // <-- syntax error
else
return t + t;
}
Run Code Online (Sandbox Code Playgroud)
doIt(aa)实例doIt化为T = AA:
double doIt<AA>(AA &t) {
if (true)
return t.Plus(t);
else
return t + t; // <-- syntax error
}
Run Code Online (Sandbox Code Playgroud)
您应该避免专门化函数模板,因为函数会过载。您可以阅读 Herb Sutter 这篇优秀的文章:为什么不专门化函数模板?