2016-07-01 22 views
5

ben aşağıdakileri yapmak istiyorum:nasıl paketi genişleme sırasında constexpr işlevini kullanabilirsiniz?

// 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>{})); 

Ancak, aşağıdaki hatayı alıyorum:

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

cevap

5

fn sabit ifadede kullanılabilir değil - bir bataklık standart blok-kapsam değişken var. Functor'ı bir tip olarak geçmek zorundasınız.

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

Ve constexpr bir işlev işaretçisi türü bir parçası değildir aslında yanı sıra

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

, square bir şablon olarak buna bir işaretçi oluşamaz, böylece işlevini yeniden Her zamanki örtülü çürüme tarafından.

Ama bu işi yapmak için make_type işlevinin imzasını değiştirmek gerekli değildir.

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

Ve böyle diyoruz: Bir functor olarak Square yeniden yazma C++ 17 yılında

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

Bir constexpr lambda kullanmak mümkün olacak:

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

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