提问人:sameer karjatkar 提问时间:8/10/2023 最后编辑:sameer karjatkar 更新时间:8/11/2023 访问量:90
模板函数覆盖
template function override
问:
我正在尝试为基于类型的函数创建一个模板 speacialization
因此,例如,对于我有的类型编号
template <class ElementType, typename = typename TEnableIf<TNot<TIsSame<ElementType, double>>::Value>::Type>
void WriteExtras(IGLTFJsonWriter &Writer, const FString &Key, const TSharedPtr<FJsonValue> &Value) const
{
Writer.Write(Key, float(Value->AsNumber()));
// Perform further processing or write logic for double
}
现在我想再有一个定义,但对于布尔......但如果我尝试这样做
template <class ElementType, typename = typename TEnableIf<TNot<TIsSame<ElementType, bool>>::Value>::Type>
void WriteExtras(IGLTFJsonWriter &Writer, const FString &Key, const TSharedPtr<FJsonValue> &Value) const
{
Writer.Write(Key, Value->AsBool());
// Perform further processing or write logic for double
}
我收到错误Function already defined
我将函数模板称为
WriteExtras< EJson>(Writer,Key, Pair.Value);
EJson 是一个枚举
enum class EJson
{
None,
Null,
String,
Number,
Boolean,
Array,
Object
};
经过@Jan建议,以下是我的模板实现
template <bool 条件,typename T = void> 使用 EnableIf_t = typename TEnableIf<Condition, T>::type;
template <class ElementType>
auto WriteCustom(IGLTFJsonWriter& Writer, const FString& Key, const TSharedPtr<FJsonValue>& Value) const
->EnableIf_t<TNot<TIsSame<ElementType, FString>>::Value>
//->TEnableIf<TIsSame<ElementType, FString>::Value>
{
Writer.Write(Key, Value->AsString());
const FText Title = FText::FromString(TEXT("Template"));
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(TEXT("FString")), &Title);
}
template <class ElementType>
auto WriteCustom(IGLTFJsonWriter& Writer, const FString& Key, const TSharedPtr<FJsonValue>& Value) const
->EnableIf_t<TNot<TIsSame<ElementType, bool>>::Value>
//->TEnableIf<TIsSame<ElementType, FString>::Value>
{
Writer.Write(Key, Value->AsBool());
const FText Title = FText::FromString(TEXT("Template"));
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(TEXT("Bool")), &Title);
}
当我尝试打电话时
WriteCustom<EJson>(Writer,Key, Pair.Value);
它给出错误
答:
2赞
Jan Schultke
8/10/2023
#1
这两个函数实际上声明了相同的函数:
template <class ElementType,
class = typename TEnableIf<TNot<TIsSame<ElementType, double>>::Value>::Type>
void WriteExtras(/* same as below */) const;
template <class ElementType,
class = typename TEnableIf<TNot<TIsSame<ElementType, bool>>::Value>::Type>
void WriteExtras(/* same as above */) const;
它们之间的唯一区别是模板参数的默认参数,但这并不能使其中一个参数成为单独的实体。这就像写:
int foo(int x = 0);
int foo(int x = 1);
正确执行 SFINAEenable_if
您需要在函数签名中的其他位置(例如参数、noexcept 规范、返回类型等)执行 SFINAE(或您的自定义模仿)。对于函数,最好的方法之一是使用返回类型,因为它不会更改模板参数列表:std::enable_if
// convenience alias (since C++14)
// similar to std::enable_if_t
template <bool Condition, typename T = void>
using EnableIf_t = typename EnableIf<Condition, T>::type;
// note: you could also make a convenience variable template for TIsSame
template <class ElementType>
auto WriteExtras(/* ... */) const
-> TEnableIf_t<not TIsSame<ElementType, double>::Value>;
// note: TNot is unnecessary, you can just write '!' or 'not' here
template <class ElementType>
auto WriteExtras(/* ... */) const
-> TEnableIf_t<not TIsSame<ElementType, bool>::Value>;
或者,有些人更喜欢在另一个非类型模板参数 (NTTP) 中执行 SFINAE 部分:
template <class ElementType, TEnableIf_t<not TIsSame<ElementType, double>::Value, int> = 0>
void WriteExtras(/* ... */) const;
这样做的原因是,该 NTTP 的函数类型不同,因此函数实际上并不相同。也无法通过显式提供模板参数来绕过约束。
替代解决方案
但是,您是否应该在这里使用 SFINAE 也是非常值得怀疑的。您可以使用 (C++17) 实现相同的目的:if constexpr
template <class ElementType>
void WriteExtras(/* ... */) const {
if constexpr (TIsSame<ElementType, double>::value) {
// ...
}
else if constexpr (TIsSame<ElementType, bool>::value) {
// ...
}
else {
// TODO: handle this error case somehow
// (specifics may depend on language version and compiler)
}
}
您还可以使用完全专用化,只要只有一个模板参数:
template <class ElementType> // Inside class
// Primary template is defined as deleted, so only calling
// the specializations is allowed.
void WriteExtras(/* ... */) const = delete;
template <> // Outside class
void JsonWriter::WriteExtras<double>(/* ... */) const { /* ... */ }
// More specializations here ...
评论
0赞
sameer karjatkar
8/10/2023
我不能在模板中添加或条件<class ElementType, typename = typename TEnableIf<TNot<TIsSame<ElementType, double> ||bool >::Value>::Type> void WriteExtras(IGLTFJsonWriter& Writer, const FString& Key, const TSharedPtr<FJsonValue>& Value) const ?
0赞
Jan Schultke
8/10/2023
@sameerkarjatkar在一定程度上可以,但不能使用类型参数的默认参数。我已经扩展了答案。
0赞
sameer karjatkar
8/10/2023
它需要 C++ 20 吗?我在 Vs 2022 上遇到错误,类型为“TEnableIf<TNot<TIsSame<T,double>>::Value,int>”的非类型模板参数至少需要“/std:c++20”
0赞
Jan Schultke
8/10/2023
@sameerkarjatkar再看一遍,它只是 ,这使得 template 参数有效地成为 ,因为它使用了便利别名。TEnableIf_t
int
1赞
Jan Schultke
8/10/2023
你能在编译器资源管理器或其他东西上重现错误吗?
评论
double
bool
double
bool
EJson
WriteExtras<float>(Writer,Key, Pair.Value);
WriteExtras<EJson::Number>(Writer,Key, Pair.Value);
EJson