考虑以下计划:
// Include
#include <iostream>
#include <type_traits>
#include <utility>
#include <tuple>
#include <string>
// Base class
template <class Crtp, class... Types>
struct Base
{
// Constructor calling the transmute function
template <class... OtherTypes>
explicit inline Base(const OtherTypes&... source)
: _data(transmute<std::tuple<Types...>>(std::forward_as_tuple(source...)))
{;}
// Transmute: create a new object
template <class Output>
static constexpr Output transmute()
{return Output();}
// Transmute: forward existing object
template <class Output,
class Input,
class = typename std::enable_if<
std::is_convertible<
typename std::remove_cv<typename std::remove_reference<Input>::type>::type,
typename std::remove_cv<typename std::remove_reference<Output>::type>::type
>::value
>::type>
static constexpr Input transmute(Input&& input)
{return std::forward<Input>(input);}
// Transmute: recursive transmutation
template <class Output,
class... Input,
class = typename std::enable_if<
(sizeof...(Input) <= std::tuple_size<Output>::value)
&& (sizeof...(Input) != std::tuple_size<Output>::value)
>::type>
static constexpr Output transmute(const Input&... input)
{return transmute<Output>(input..., typename std::tuple_element<sizeof...(Input), Output>::type());}
// Transmute: final step
template <class Output,
class... Input,
class = typename std::enable_if<
(sizeof...(Input) == std::tuple_size<Output>::value)
&& (sizeof...(Input) != 0)
>::type>
static constexpr Output transmute(Input&&... input)
{return transmute<Output>(std::forward_as_tuple(std::forward<Input>(input)...));}
// Data member
std::tuple<Types...> _data;
};
// Derived class
struct Derived
: public Base<Derived, std::string, bool>
{
// Universal reference constructor
template <class... Misc>
explicit inline Derived(Misc&&... misc)
: Base<Derived, std::string, bool>(std::forward<Misc>(misc)...)
{;}
};
// Main
int main(int argc, char* argv[])
{
Derived a("hello"); // Boom !!!!
return 0;
}
如果你试图编译它,编译器将“爆炸”,用模板模板模板抛出令人印象深刻的错误......
我的问题很简单:问题在哪里以及如何解决?
答案 0 :(得分:4)
如果我理解你的意图,看起来你想要的是将M
个参数传递给大小为std::tuple<>
的{{1}},N
。如果M <= N
,请填写未提供类型的默认构造值的参数。
如果是这种情况,M < N
的构造函数应为:
Base
这样它将通过递归,最终,然后template <class... OtherTypes>
explicit inline Base(const OtherTypes&... source)
: _data(transmute<std::tuple<Types...>>(source...))
{;}
。
替代解决方案:
注意: forward_as_tuple
及相关助手的实施将被省略。您可以参考论文N3658和实施here。
std::integer_sequence