11

だから私はこの本当に醜いコードを持っています:

template <typename T>
std::conditional_t<sizeof(T) == sizeof(char),
                   char,
                   conditional_t<sizeof(T) == sizeof(short),
                                 short,
                                 conditional_t<sizeof(T) == sizeof(long),
                                               long,
                                               enable_if_t<sizeof(T) == sizeof(long long),
                                                           long long>>>> foo(T bar){return reinterpret_cast<decltype(foo(bar))>(bar);}

ネストされたconditional_ts を使用して、ある種のケースステートメントを作成しています。これをよりエレガントに実現するものはありますか、それとも独自のテンプレート化されたケースステートメントを作成する必要がありますか?

reinterpret_cast注: この の使用が悪いことを実際に認識しています。

4

5 に答える 5

3

同じサイズのタイプがコンバーチブルではない可能性があるというリスクを理解している限り、mpl::map..

typedef map<
      pair<int_<sizeof(char)>, char>,
      pair<int_<sizeof(short)>, short>,
      pair<int_<sizeof(int)>, int>,
      pair<int_<sizeof(long long)>, long long>
    > m;

例えば

#include <algorithm>
#include <iostream>

#include <boost/mpl/at.hpp>
#include <boost/mpl/map.hpp>

using namespace boost::mpl;

typedef map<
      pair<int_<sizeof(char)>, char>,
      pair<int_<sizeof(short)>, short>,
      pair<int_<sizeof(int)>, int>,
      pair<int_<sizeof(long long)>, long long>
    > m;

template <typename T>
typename at<m, int_<sizeof(T)>>::type foo(T bar)
{ return reinterpret_cast<decltype(foo(bar))>(bar); }


struct doh
{
    std::string a, b, c;
};

int main()
{
    {
      char c;
      static_assert(std::is_same<decltype(foo(c)), char>::value, "error");
    }
    {
      short c;
      static_assert(std::is_same<decltype(foo(c)), short>::value, "error");
    }
    {
      int c;
      static_assert(std::is_same<decltype(foo(c)), int>::value, "error");
    }
    {
      long long c;
      static_assert(std::is_same<decltype(foo(c)), long long>::value, "error");
    }
    {
      double c;
      static_assert(std::is_same<decltype(foo(c)), long long>::value, "error");
    }    
    {
      doh c;
      static_assert(std::is_same<decltype(foo(c)), void_>::value, "error");
    }    
}
于 2015-02-24T15:30:36.127 に答える
1

タイプタグ:

template<class T>struct tag{using type=T;};

void_t(お近くのコンパイラに C++17 で提供されます):

template<class...>struct voider{using type=void;};
template<class...Ts>using void_t=typename voider<Ts...>::type;

enable_first_tstd::enable_if( がないことに注意してください)のパックを取り、_t最初にテストに合格したものを返します。を使用tag<X>して置き換えることができますstd::enable_if<true, X>

template<class T,class=void>struct has_type:std::false_type{};
template<class T>struct has_type<T, void_t<typename T::type>>:std::true_type{};

namespace details {
  template<class, class...Ts>
  struct enable_first {};
  template<class T0, class...Ts>
  struct enable_first<std::enable_if_t< !has_type<T0>{} >, T0, Ts... >:enable_first<void, Ts...> {};
  template<class T0, class...Ts>
  struct enable_first<std::enable_if_t<  has_type<T0>{} >, T0, Ts...>:T0 {};
}

template<class...Ts>using enable_first_t=typename details::enable_first<void, Ts...>::type;

template<class T>
using result = enable_first_t<
  std::enable_if<sizeof(T)==sizeof(char), char>,
  std::enable_if<sizeof(T)==sizeof(short), short>,
  std::enable_if<sizeof(T)==sizeof(long), long>,
  tag<int> // default
>;

これは とよく似た動作をしますswitchが、ステートメントは完全なブール式です。

実際の例

于 2015-02-24T15:40:56.363 に答える