std :: vector etc不必要(错误地?)实例化嵌套模板参数类型

时间:2014-05-31 14:11:58

标签: c++ templates c++11 language-lawyer

以下代码编译得很好,即使很难std::plus<void>也是非法的(在C ++ 11中)。

template < typename > struct data {};
data<std::plus<void>> x; // does not attempt to complete std::plus<void>

这是有道理的,因为data<std::plus<void>>不需要实例化std::plus<void>。但是,它在构造std::vector时无法编译,这会以某种方式导致std::plus<void>的实例化。

std::vector<data<std::plus<void>>> v;

错误是:

/opt/local/libexec/llvm-3.5/bin/../include/c++/v1/functional:496:29: error: cannot form a reference to 'void'
_Tp operator()(const _Tp& __x, const _Tp& __y) const
/opt/local/libexec/llvm-3.5/bin/../include/c++/v1/type_traits:2055:27: note: in instantiation of
template class 'std::__1::plus<void>' requested here
decltype(__is_constructible_test(declval<_Tp>(), declval<_Args>()...))

g ++ 4.8或std::list上的类似错误。

这是预期的行为吗?

1 个答案:

答案 0 :(得分:3)

  

以下代码编译得很好,即使是std::plus<void>也很难   非法的(在C ++ 11中)。

自C ++ 1以来,该标准保证了以下明确的专业化:

template <> struct plus<void> {
    template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
    -> decltype(std::forward<T>(t) + std::forward<U>(u));

    typedef unspecified is_transparent;
};

实际上不完整的模板参数(例如C ++ 11中void的{​​{1}})的问题是:

  

特别是,在以下情况下效果未定义:

     

- 如果使用不完整类型(3.9)作为模板参数   实例化模板组件,除非特别允许   该组件。

您的程序遇到未定义行为的原因是std::plus使用std::plus实例化,这是一个不完整的类型。

写作的原因

void

导致编译器错误(导致UB)是模板的成员函数在使用之前未实例化