考虑以下简单(在模板问题的范围内)示例:
#include <iostream>
template <typename T>
struct identity;
template <>
struct identity<int> {
using type = int;
};
template<typename T> void bar(T, T ) { std::cout << "a\n"; }
template<typename T> void bar(T, typename identity<T>::type) { std::cout << "b\n"; }
int main ()
{
bar(0, 0);
}
Run Code Online (Sandbox Code Playgroud)
clang和gcc都在那里打印"a".根据[temp.deduct.partial]和[temp.func.order]中的规则,为了确定部分排序,我们需要合成一些独特的类型.所以我们有两次尝试扣除:
+---+-------------------------------+-------------------------------------------+
| | Parameters | Arguments |
+---+-------------------------------+-------------------------------------------+
| a | T, typename identity<T>::type | UniqueA, UniqueA |
| b | T, T | UniqueB, typename identity<UniqueB>::type |
+---+-------------------------------+-------------------------------------------+
Run Code Online (Sandbox Code Playgroud)
c++ templates partial-ordering language-lawyer overload-resolution
根据[temp.class.order]§14.5.5.2,t在此示例中选择部分特化:
template< typename >
struct s { typedef void v, w; };
template< typename, typename = void >
struct t {};
template< typename c >
struct t< c, typename c::v > {};
template< typename c >
struct t< s< c >, typename s< c >::w > {};
t< s< int > > q;
Run Code Online (Sandbox Code Playgroud)
等效f于此示例中的重载选择:
template< typename >
struct s { typedef void v, w; };
template< typename, typename = void >
struct t {};
template< typename …Run Code Online (Sandbox Code Playgroud) c++ templates partial-specialization partial-ordering language-lawyer
我试图重现视频C++ Weekly - Ep 48 - C++ 17的Variadic的结果using,但失败了.问题可以简化为以下代码段.
假设我有这样的通用结构:
template <class... T>
struct Container {
template <class... U>
Container(U... us) {}
};
Run Code Online (Sandbox Code Playgroud)
现在我可以Container用任何参数初始化a ,比如
auto d = Container(1,2,3);
Run Code Online (Sandbox Code Playgroud)
但是,编译器永远不会知道它是什么类型d.要解决这个问题,我们应该提供一个扣除指南,例如
template <class... U>
Container(U...) -> Container<double, int, bool>
Run Code Online (Sandbox Code Playgroud)
根据视频,编译器现在应该知道d有类型Container<double, int, bool>.
但是,代码无法按预期工作.打印时typeid(d).name(),无论我如何更改演绎指南中的返回类型,输出将始终被9ContainerIJEE转换为Container<>,表明此指南根本不指导编译器.
我正在使用gcc-7-snapshot-20170402,视频中的编译器是gcc-7-snapshot-20170130.
谁能告诉我这里有什么问题?
顺便说一句,如果我明确写
Container<bool, int> d = Container(1,2,3);
Container<char, char, char> d = Container(1,2,3);
...
Run Code Online (Sandbox Code Playgroud)
代码将始终编译,并提供像9containerIJbiEE …
考虑:
#include <type_traits>
template <typename>
struct Tag {};
template <typename T>
auto tag = Tag<T>{};
template <typename...>
struct SelectorImpl;
// 1
template <auto... xs>
struct SelectorImpl<std::integral_constant<decltype(xs), xs>...>
{};
// 2
template <typename T, Tag<T>* tag, auto... xs>
struct SelectorImpl<std::integral_constant<decltype(tag), tag>,
std::integral_constant<decltype(xs), xs>...>
{};
template <auto... params>
struct Selector
: SelectorImpl<std::integral_constant<decltype(params), params>...>
{};
int main() {
Selector<&tag<int>, 1, 2>{};
}
Run Code Online (Sandbox Code Playgroud)
gcc和clang都无法编译它,报告这些特殊化SelectorImpl是不明确的.我相信专业化#2更专业.我错了吗?难道同样的问题,因为在这里?这是一个错误吗?