【发布时间】:2013-12-12 23:02:27
【问题描述】:
考虑以下程序:
// 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;
}
如果你试图编译它,编译器会“爆炸”,抛出一个相当令人印象深刻的错误,模板的模板模板......
我的问题很简单:问题出在哪里,如何解决?
【问题讨论】:
-
因此类似于摆出整个程序并输入,然后说它“运行时崩溃”。出了什么问题?做更少的事情。测试每个组件。找到从测试和工作到测试和失败的变化。包括有关您正在尝试做的事情的大量文档。尝试用更少的麻烦来简化并产生相同的错误。
-
(sizeof...(Input) <= std::tuple_size<Output>::value) && (sizeof...(Input) != std::tuple_size<Output>::value)这看起来很可疑。 -
: _data(transmute<std::tuple<Types...>>(source...))并编译(删除了std::forward_as_tuple)。不过,不确定它是否正确。但据我了解您的元编程,作为元组的转发是不正确的:最后一步期望所有参数 not 都包装在一个元组中;在您当前的代码中,从"hello"创建的std::tuple<const char(&)[6]>不能转换为std::string,因此永远不会发生转发。 -
+1,我刚刚发现这是 3 分钟前错误的根源。
-
只接受 mpark 的。写重复的答案没有任何好处。
标签: c++ c++11 metaprogramming template-meta-programming sfinae