2012-11-06 31 views
3

我想弄清楚哪種是最可行的方式實現函數的可變類型列表。例如,計算所有類型的最大大小。我知道有幾種方法可以完成這樣的任務,但是我想知道什麼時候選擇哪種策略。通過可變參數模板計算函數

這是我會考慮的機制(有可能存在更多的,請註明如果是這樣):

  • 型性狀(最好簡潔使用的聲明):

    template <typename Head> 
    using max_size = typename std::integral_constant<size_t, sizeof(Head)>::type; 
    
    template <typename Head, typename... Tail> 
    using max_size = ?; 
    
  • constexpr功能:

    template <typename Head> 
    constexpr size_t max_size() { return sizeof(Head); } 
    
    template <typename Head, typename... Tail> 
    constexpr size_t max_size() { ? } 
    

我的問題是雙重的:

  1. 什麼功能計算確定選擇何種策略?

  2. 在每種情況下,上述最大尺寸示例的示例實現將如何看起來如何?

回答

5

我個人更喜歡功能而不是特質,我覺得它們更容易操作,更自然。但是,這肯定是主觀的)

#include <iostream> 

template <typename Head> 
constexpr size_t max_size() { return sizeof(Head); } 

template <typename Head, typename Next, typename... Tail> 
constexpr size_t max_size() { 
    return max_size<Head>() > max_size<Next, Tail...>() ? 
      max_size<Head>() : max_size<Next, Tail...>(); 
} 

int main() { 
    std::cout << "int: " << max_size<int>() << "\n"; 
    std::cout << "char, short, int: " << max_size<char, short, int>() << "\n"; 
    std::cout << "char, double, int: " << max_size<char, double, int>() << "\n"; 
} 

在行動,在liveworkspace

int: 4 
char, short, int: 4 
char, double, int: 8 
+0

這是可用答案的最短和最清晰的解決方案。另一個重點是它不依賴Boost。 – mavam

+0

@MatthiasVallentin:是的,我傾向於使用'constexpr',因爲它們比元編程技巧更具可讀性。更少的樣板,更多閱讀功能的習慣。 –

3

我就從嚴格使用constexpr,因爲它們很難組成望而卻步。例如,我甚至不確定constexpr的高階元函數是可能的,如果是的話,他們使用函數指針作爲醜陋的模板參數。

在一般情況下,我開始與元函數類:

struct max_size { 
    template<typename... Ts> 
    struct apply : parampack_foldl::apply<boost::mpl::quote2<boost::mpl::max>, typename boost::mpl::sizeof_<Ts>::type...>; 
}; 

然後創建一個別名,以減輕打字:

template<typename... Ts> 
using MaxSize = typename max_size::apply<Ts>::type; 

或者,創建一個constexpr功能:

template <typename... Ts> 
constexpr size_t max_size() { return max_size::apply<Ts...>::type::value; } 

第二步實際上只是一個風格問題,真正重要的是你有第一個給予y的東西與你一起工作最多。

+0

我喜歡高階元功能的想法。這將允許編寫一個'max'函數並傳遞另一個元函數來計算大小。它實際上似乎與constexpr函數一起工作良好:http://liveworkspace.org/code/5809994d109ad35a1b68d2beb81b3ddd(該鏈接指向Matthieu的示例,稍作修改。) – mavam

1

爲了完整,還存在繼承的技術:

#include <cstddef> 
using std::size_t; 

template<size_t ...S> struct max_size_t; 

template<size_t S1, size_t S2, size_t ...Rest> 
struct max_size_t<S1, S2, Rest...> 
    : max_size_t<(S2 < S1) ? S1 : S2, Rest...> { 
}; 

template<size_t S> 
struct max_size_t<S> { 
    static const int value = S; 
}; 

template<> struct max_size_t<> { 
    static const int value = 0; 
}; 

template<typename ...T> struct max_size : max_size_t<sizeof(T)...> {}; 

// Using the same test-harness as Matthieu M: 
#include <iostream> 

int main() { 
    std::cout << "int: " << max_size<int>::value << "\n"; 
    std::cout << "char, short, int: " << max_size<char, short, int>::value << "\n"; 
    std::cout << "char, double, int: " << max_size<char, double, int>::value << "\n"; 
    return 0; 
} 
liveworkspace

同樣。

儘管這不是一種方法,我會選擇來實現max_size,這是非常方便的時候所需要的功能是它返回一個類型(高人爲的例子如下):

template<typename T1, typename T2, bool B=(sizeof(T1)>sizeof(T2))> struct selector; 
template<typename T1, typename T2> struct selector<T1, T2, true> { using type = T1; }; 
template<typename T1, typename T2> struct selector<T1, T2, false> { using type = T2; }; 

template<typename T1, typename ...Rest> struct largest_type; 

template<typename T1, typename T2, typename ...Rest> 
struct largest_type<T1, T2, Rest...> 
    : largest_type<typename selector<T1, T2>::type, Rest...> {}; 

template<typename T1> struct largest_type<T1> { using type = T1; }; 

#include <iostream> 
int main() { 
    static const unsigned long long u = 1ULL << 63; 
    std::cout << "int: " << typename largest_type<int>::type(u) << "\n"; 
    std::cout << "int, double: " << typename largest_type<int, double>::type(u) << "\n"; 
    std::cout << "short, float, long long: " << typename largest_type<short, float, long long>::type(u) << "\n"; 
return 0; 
} 

看到它here

+0

+1用於使用不同技術的詳盡答案 – mavam