相关疑难解决方法(0)

类模板特化部分排序和函数合成

选择哪个类模板特化的首选规则包括将特化重写为函数模板,并通过函数模板[temp.class.order]的排序规则确定哪个函数模板更加专业化.考虑这个例子,然后:

#include <iostream>

template <class T> struct voider { using type = void; };
template <class T> using void_t = typename voider<T>::type;

template <class T, class U> struct A { };

template <class T> int foo(A<T, void_t<T>> ) { return 1; }
template <class T> int foo(A<T*, void> )     { return 2; }

int main() {
    std::cout << foo(A<int*, void>{});
}
Run Code Online (Sandbox Code Playgroud)

gcc和clang都打印2在这里.这是有道理的一些前面的例子-推导对非推测的情况下(voidvoid_t<T>)只是忽略,所以推断<T, void_t<T>>反对<X*, void>成功,但推断<T*, void>针对<Y, void_t<Y>>在两个参数失败.精细. …

c++ templates partial-ordering language-lawyer

43
推荐指数
1
解决办法
1416
查看次数

具有未受限上下文的函数模板的部分排序

在阅读另一个问题时,我遇到了部分排序问题,我将其缩减为以下测试用例

template<typename T>
struct Const { typedef void type; };

template<typename T>
void f(T, typename Const<T>::type*) { cout << "Const"; } // T1

template<typename T>
void f(T, void*) { cout << "void*"; } // T2

int main() {
  // GCC chokes on f(0, 0) (not being able to match against T1)
  void *p = 0;
  f(0, p);
}
Run Code Online (Sandbox Code Playgroud)

对于两个函数模板,进入重载分辨率的特化的函数类型是void(int, void*).但是,部分排序(根据comeau和GCC)现在说第二个模板更专业.但为什么?

让我通过部分排序,并显示我有问题的地方.可以Q被用于确定根据偏序的独特由上型14.5.5.2.

  • 变换参数列表T1(Q插入)(Q, typename Const<Q>::type*).参数的类型是AT=(Q, void*)
  • 转换参数列表T2 …

c++ templates partial-ordering function-templates template-argument-deduction

22
推荐指数
1
解决办法
2161
查看次数

模板偏序 - 为什么部分演绎在这里成功

考虑以下简单(在模板问题的范围内)示例:

#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)

根据Richard Corden的回答 …

c++ templates partial-ordering language-lawyer overload-resolution

20
推荐指数
2
解决办法
1166
查看次数

SFINAE模板专业化优先级

#include <iostream>
#include <array>
#include <vector>

template <typename T, typename SFINAE=void>
struct trait;

template <typename T>
struct trait<T, decltype(
  std::declval<const T&>().begin(),
  std::declval<const T&>().end(),
  void()
)> {
  static const char* name() { return "Container"; }
};

template <typename T, std::size_t N>
struct trait<std::array<T,N>> {
  static const char* name() { return "std::array"; }
};

int main(int argc, char* argv[]) {
  std::cout << trait<std::vector<int>>::name() << std::endl;
  std::cout << trait<std::array<int,2>>::name() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

我期待第三个模板比第二个模板更专业,但我得到了一个模糊的模板实例化.

有没有办法让第三个模板更专业?明确检查是否Tstd::array在第二个模板不会为我工作.我正在写一个图书馆,希望用户能够定义他们自己的专业trait.第二个模板旨在成为没有更具体特征的容器的通用特化.

c++ templates sfinae template-specialization

16
推荐指数
1
解决办法
348
查看次数

可变参数模板构造函数的扣除指南失败

我试图重现视频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 …

c++ gcc c++17

6
推荐指数
1
解决办法
899
查看次数