簡體   English   中英

如何在C ++中比較兩個類型名稱的相等性?

[英]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 ,你可以用一種非常干凈的方式實現結果(使用constexpris_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);
}

看到它在這里工作。

,最好的解決方案是if constexpr

這適用於:

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中的一個並在編譯時返回它。 然后我們用ab調用拾取的lambda。 所以只有有效的一個用ab的類型編譯。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM