我希望能够做到以下几点:
save
以下答案并不令人满意:他们只想检查参数包是否属于单一类型,但我想在参数中将值正确转换为它(否则它不起作用)。 / p>
C++ parameter pack, constrained to have instances of a single type?
Parameter with non-deduced type after parameter pack
我也不能使用initializer_list,因为我无法计算传递给#include <array>
struct blah { };
template<typename... Args>
constexpr auto foo(Args&&... args)
{
return std::array<blah, sizeof...(Args)>{{ args... }};
}
auto res = foo({}, {});
类型的参数数量。
而且我特别想要输入array
。
我有什么可能性?
答案 0 :(得分:4)
lazies(C ++ 17)稍微扩展approach of Jarod42:
#include <utility>
#include <array>
struct blah {};
template <class T, std::size_t I>
using typer = T;
template <class T, std::size_t N, class = std::make_index_sequence<N>>
struct bar_impl;
template <class T, std::size_t N, std::size_t... Is>
struct bar_impl<T, N, std::index_sequence<Is...>> {
static auto foo(typer<T, Is>... ts) {
return std::array<T, N>{{ts...}};
}
};
template <class T = blah, std::size_t N = 10, class = std::make_index_sequence<N>>
struct bar;
template <class T, std::size_t N, std::size_t... Is>
struct bar<T, N, std::index_sequence<Is...>>: bar_impl<T, Is>... {
using bar_impl<T, Is>::foo...;
};
int main() {
bar<>::foo({}, {});
}
修改强>
某些C ++ 14解决方案(如max66所述)甚至比我预期的更简单:
#include <utility>
#include <array>
struct blah {};
template <class T, std::size_t I>
using typer = T;
template <class T = blah, std::size_t N = 10, class = std::make_index_sequence<N>>
struct bar;
template <class T, std::size_t N, std::size_t... Is>
struct bar<T, N, std::index_sequence<Is...>>: bar<T, N - 1> {
using bar<T, N - 1>::foo;
static auto foo(typer<T, Is>... ts) {
return std::array<T, N>{{ts...}};
}
};
template <class T>
struct bar<T, 0, std::index_sequence<>> {
static auto foo() {
return std::array<T, 0>{{}};
}
};
int main() {
bar<>::foo({}, {});
}
再修改一次:
这个(由Jarod42建议)提供与OP的问题完全相同的调用语法:
#include <utility>
#include <array>
struct blah {};
template <class T, std::size_t I>
using typer = T;
template <class T = blah, std::size_t N = 10, class = std::make_index_sequence<N>>
struct bar;
template <class T, std::size_t N, std::size_t... Is>
struct bar<T, N, std::index_sequence<Is...>>: bar<T, N - 1> {
using bar<T, N - 1>::operator();
auto operator()(typer<T, Is>... ts) {
return std::array<T, N>{{ts...}};
}
};
template <class T>
struct bar<T, 0, std::index_sequence<>> {
auto operator()() {
return std::array<T, 0>{{}};
}
};
bar<> foo;
int main() {
foo({}, {});
}
答案 1 :(得分:2)
好吧,如果你有能力改变语法小位,这是我设法找到的最好的:
#include <array>
// to_array implementation taken from
// http://en.cppreference.com/w/cpp/experimental/to_array
namespace detail {
template <class T, std::size_t N, std::size_t... I>
constexpr std::array<std::remove_cv_t<T>, N>
to_array_impl(T (&a)[N], std::index_sequence<I...>)
{
return { {a[I]...} };
}
}
template <class T, std::size_t N>
constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&a)[N])
{
return detail::to_array_impl(a, std::make_index_sequence<N>{});
}
// End of to_array implementation
struct blah { };
template<std::size_t N>
constexpr auto foo(const blah(&arr)[N])
{
return to_array(arr);
}
int main()
{
auto res = foo({{}, {}});
return 0;
}
如您所见,foo({}, {})
成了foo({{}, {}})
。
这是一个工作示例:https://ideone.com/slbKi3
您想要它的方式(foo({}, {})
)的问题是编译器无法知道它应该将{}
转换为什么。
我试图找到一种方法让它知道,但它根本就没有听。
答案 2 :(得分:2)
如果您按照Telokis的建议接受添加支持级别foo()
auto res = foo( { {}, {} } );
你可以使用Telokis提出的C风格的数组技巧和一个简单的循环来初始化返回值
template <std::size_t N>
constexpr std::array<blah, N> foo (const blah(&arr)[N])
{
std::array<blah, N> ret;
for ( auto i = 0U ; i < N ; ++i )
ret[i] = arr[i];
return ret;
}
不幸的是,operator[]
的{{1}}只有std::array
才从C ++ 17开始,所以前面的constexpr
实际上只有foo
从C +开始17。
所以你可以打电话给
constexpr
也在C ++ 11和C ++ 14中,但是
auto res = foo( { {}, {} } );
仅从C ++ 17开始。