2016-07-01 13 views
5

私は次の操作を実行したい:パック展開中にconstexpr関数を使用するにはどうすればよいですか?

// have a constexpr function 
template<class T> 
constexpr T square(T const i) 
{ 
    return i * i; 
} 

// transform a std::integer_sequence<> by calling the constexpr function on every integer 
template<class Fn, class T, T... values> 
static constexpr auto make_type(Fn fn, std::integer_sequence<T, values...>) 
{ 
    return std::integer_sequence<T, fn(values)...>{}; 
} 

// so that I can use it like so 
using type = decltype(make_type(square, std::integer_sequence<int, 1, 2, 3>{})); 

しかし、私は次のエラーを取得:

...\main.cpp|19|error: 'fn' is not a constant expression|

答えて

5

fnは定数式では使用できません - それは沼地標準ブロック・スコープの変数です。ファンクタを型として渡す必要があります。

template <typename Fn, typename T, T... values> 
static constexpr std::integer_sequence<T, Fn{}(values)...> 
make_type(std::integer_sequence<T, values...>) {return {};} 

そしてconstexprは、関数ポインタの型の一部ではないという事実に加えて

struct Square { 
    template <typename T> constexpr T operator()(T const& t) 
    {return t*t;} 
}; 
1

は、squareがテンプレートであるとして、あなたはそれへのポインタを形成することはできませんので、あなたの関数を書き換えます通常の陰的な減衰によって。

しかし、この作業を行うにはmake_type関数の署名を変更する必要はありません。

struct Square { 
    template<class T> 
    constexpr T operator()(T const& i) 
    { 
     return i * i; 
    } 
}; 

そして、このようにそれを呼び出す:ファンクターとしてSquareを書き直しC++ 17では

using type = decltype(make_type(square{}, std::integer_sequence<int, 1, 2, 3>{})); 

あなたがconstexprラムダを使用することができます:

constexpr auto square = [](auto const& i) { return i * i; }; 

using type = decltype(make_type(square, std::integer_sequence<int, 1, 2, 3>{})); 
関連する問題