[英]How to compare two typenames for equality in C++?
假設我有一個函數的模板,比方說
template<typename T>
func(T a, T b, ...) {
...
for (const auto &single : group) {
...
auto c = GivenFunc1(a, b, single, ...);
... }
...
}
但是,對於T是一種特殊類型,比如“SpecialType”,我希望c
由“GivenFunc2”而不是“GivenFunc1”計算。 但是,我不想為“SpecialType”編寫專門化,因為會有大量的代碼重復。 所以我想模板功能就像
template<typename T>
func(T a, T b, ...) {
...
for (const auto &single : group) {
...
auto c = (T == SpecialType) ? GivenFunc2(a, b, single, ...)
: GivenFunc1(a, b, single, ...);
... }
...
}
當然,由於“T == SpecialType”無效,因此該代碼無法編譯。 那么如何以優雅的方式編寫它呢?
它很簡單:
auto c = std::is_same_v<T, SpecialType> ? GivenFunc2(a, b, single, ...)
: GivenFunc1(a, b, single, ...);
如果您不能使用C ++ 17,請將std::is_same_v<...>
替換為std::is_same<...>::value
。
但是對於這種工作方法,兩個函數調用必須對你想要使用的每個T
都有效,即使實際上其中一個不會被執行。
如果不是這樣,你可以求助於if constexpr
:
your_type_here c;
if constexpr (std::is_same_v<T, SpecialType>)
c = GivenFunc2(a, b, single, ...);
else
c = GivenFunc1(a, b, single, ...);
(這僅適用於C ++ 17。)
如果你可以使用C ++ 17 ,你可以用一種非常干凈的方式實現結果(使用constexpr
和is_same
):
template<typename T>
func(T a, T b, ...) {
// ...
if constexpr (std::is_same_v<T, SpecialType>) {
// call GivenFunc2
} else {
// call GivenFunc1
}
// ...
}
預C ++ 17可以使用諸如實現相同的結果SFINAE
或“TAG調度”。
此外,您可以專門參考函數調用的代碼部分(簡單並避免代碼重復)。
簡單例子在這里 :
template <typename T>
struct DispatcherFn {
auto operator()(const T&, int) {
// call GivenFunc1
}
};
template <>
struct DispatcherFn<SpecialType> {
auto operator()(const SpecialType&, int) {
// GivenFunc2
}
};
template <typename T>
void func(const T& t) {
// ... code ...
auto c = DispatcherFn<T>()(t, 49); // specialized call
}
您始終可以使用模板特化而不是模板參數的類型比較。 這是一個簡化的工作示例:
#include <iostream>
#include <string>
template<typename T>
int GivenFunc1(T a, T b) {
std::cout << "GivenFunc1()" << std::endl;
return 0;
}
template<typename T>
int GivenFunc2(T a, T b) {
std::cout << "GivenFunc2()" << std::endl;
return 1;
}
template<typename T>
void func(T a, T b) {
auto c = GivenFunc2(a, b);
std::cout << c << std::endl;
}
template<>
void func(std::string a, std::string b) {
auto c = GivenFunc1(a, b);
std::cout << c << std::endl;
}
int main() {
func(2,3);
std::string a = "Hello";
std::string b = "World";
func(a,b);
}
看到它在這里工作。
在c ++ 17中 ,最好的解決方案是if constexpr
。
在c ++ 14中,這適用於:
template<class V>
auto dispatch( V const& ) {
return [](auto&&...targets) {
return std::get<V{}>( std::forward_as_tuple( decltype(targets)(targets)... ) );
};
}
然后:
auto c = dispatch( std::is_same<T, SpecialType>{} )
(
[&](auto&& a, auto&& b){ return GivenFunc2(a, b, single...); },
[&](auto&& a, auto&& b){ return GivenFunc1(a, b, single, ...); }
)( a, b );
做你想要的。 (它也是一個返回函數返回函數的函數)
實例 。
dispatch
選擇兩個lambdas中的一個並在編譯時返回它。 然后我們用a
和b
調用拾取的lambda。 所以只有有效的一個用a
和b
的類型編譯。
將GivenFunc1
轉換為GivenFunc1
函數並將其專門化。
template <class T>
class GivenFunc
{
X operator()(T a, T b, Y single)
{
...
}
}
template <>
class GivenFunc<SpecialType>
{
X operator()(SpecialType a, SpecialType b, Y single)
{
...
}
}
然后你可以說
auto c = GivenFunc<T>()(a, b, single);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.