2017-06-15 82 views
2

下面是兩個大部分相同的模板PgmArrayPgmArrayF。第一個適用於左值參考模板參數,第二個適用於整型參數。我喜歡將這兩個合併爲一個:組合兩個幾乎相同的類模板

#include <stdint.h> 
#include <type_traits> 
#include <array> 
#include <iostream> 

template<typename T, const T&... Ts> 
struct PgmArray final { 
    static constexpr uint8_t size = sizeof... (Ts); 
    static constexpr T data[] {Ts...}; 
}; 

template<typename T, T... Ts> 
struct PgmArrayF final { 
    static constexpr uint8_t size = sizeof... (Ts); 
    static constexpr T data[] {Ts...}; 
}; 

struct A{ 
    uint8_t m = 0; 
}; 

constexpr A a1{1}; 
constexpr A a2{2}; 

constexpr auto x1 = PgmArray<A, a1, a2>{}; // ok 
constexpr auto x2 = PgmArrayF<int, 1, 2>{}; // ok 

//constexpr auto x3 = PgmArrayF<A, a1, a2>{}; // nok 
//constexpr auto x4 = PgmArray<int, 1, 2>{}; // nok 

int main() { 
} 

回答

2

我們只是扭轉什麼@bolov做,並把操作進入參數包的類型:

// separate alias template not strictly necessary, but easier for readability 
template<class T> 
using maybe_cref = std::conditional_t<std::is_integral_v<T>, T, const T&>; 

template <typename T, maybe_cref<T>... Ts> 
struct PgmArray final { 
    static constexpr uint8_t size = sizeof... (Ts); 
    static constexpr T data[] {Ts...}; 
}; 
+0

優秀!不幸的是,這產生ICE與g ++> = 8.0(g ++ 7.1是好的)。 – wimalopaan

6

這不是更少的代碼,但更易於維護,如果您經常更改PgmArray。

template<typename T, T... Ts> 
struct PgmArray final { 
    static constexpr uint8_t size = sizeof... (Ts); 
    static constexpr std::decay_t<T> data[] {Ts...}; 
}; 

template<typename T> 
struct MakePgmArray { 
    using TemplateArgument = typename std::conditional_t< 
      std::is_integral_v<T>, T, const T&>; 
    template<TemplateArgument... Ts> 
    using type = PgmArray<TemplateArgument, Ts...>; 
}; 

... 

constexpr auto x1 = MakePgmArray<A>::type<a1, a2>{}; // ok 
constexpr auto x2 = MakePgmArray<int>::type<1, 2>{}; // ok 
5

通過petersohn's answer

啓發了你也可以這樣做:

template <typename U, U... Ts> 
struct PgmArray final { 
    using T = std::remove_const_t<std::remove_reference_t<U>>; 

    static constexpr uint8_t size = sizeof... (Ts); 
    static constexpr T data[] {Ts...}; 
}; 

constexpr auto x3 = PgmArray<const A&, a1, a2>{}; // ok 
constexpr auto x4 = PgmArray<int, 1, 2>{}; // ok 
+0

那是我第一次嘗試的,但是我發現寫出'PgmArray '很麻煩,這就是爲什麼我創建了e'MakePgmArray'結構以這種方式減少噪聲(儘管增加了另一種噪聲作爲副作用)。 – petersohn

+0

理想情況下,人們可以編寫'constexpr' make-helper'make_pgm_array(1,2,3)'產生'PgmArray ',但我認爲,如果不引入像'std: :interger_constant' – wimalopaan

+0

@wimalopaan用戶定義的文字可以是整型常量類型。 – Yakk

相關問題