当我用MSVC++编译以下代码时,我收到一个错误:
struct A
{
template<typename T>
void operator<<(T&& x)
{
}
};
void f()
{
}
int main()
{
A().operator<<( f ); // ok
A() << f; // error
return 0;
}
Run Code Online (Sandbox Code Playgroud)
g ++和clang都编译好这段代码.AFAIK,' ok '和' error '行完全相同,并且类型T被推导为void(&)().或者是void()和允许对函数的右值引用?如果是这样,他们的意思是什么?这样通过引用传递函数是否可以?它是否无法编译' 错误 '行的MSVC++错误?BTW,错误输出:
no operator found which takes a right-hand operand of type 'overloaded-function' (or there is no acceptable conversion)
could be 'void A::operator <<<void(void)>(T (__cdecl &&))'
with[ T=void (void) …
Run Code Online (Sandbox Code Playgroud) #include <utility>
template<class T1, class T2>
struct mypair : std::pair<T1, T2>
{ using std::pair<T1, T2>::pair; };
int main()
{
(void)std::pair(2, 3); // It works
(void)mypair(2, 3); // It doesn't work
}
Run Code Online (Sandbox Code Playgroud)
以上是否形成良好?
如果继承构造函数,是否可能在第二种情况下推导出类模板参数?构建者是否std::pair
参与创建隐式演绎指南mypair
?
我的编译器是g ++ 7.2.0.
考虑这个模板功能:
template<typename ReturnT>
ReturnT foo(const std::function<ReturnT ()>& fun)
{
return fun();
}
Run Code Online (Sandbox Code Playgroud)
为什么编译器不能ReturnT
从传递的调用签名中推断出来?
bool bar() { /* ... */ }
foo<bool>(bar); // works
foo(bar); // error: no matching function call
Run Code Online (Sandbox Code Playgroud) 这类似于问题,但更具体的情况.这次,没有编译器按预期工作.
template<class T>
struct nondeduced
{
using type = T;
};
template<class T>
using nondeduced_t = typename nondeduced<T>::type;
template<class... T, class U>
void f(void(*)(nondeduced_t<T>..., U)) {}
void g(int, char) { }
int main()
{
f<int>(g); // error?
}
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,T
无法推导出参数包,但编译器应该能够U
在显式参数替换pack之后推导出T
(即int
在这种情况下为single ).
预计上述内容也可以在没有nondeduced_t
诀窍的情况下工作:
template<class... T, class U>
void f(void(*)(T..., U)) {}
Run Code Online (Sandbox Code Playgroud)
因为T
根据[temp.deduct.type] p5,参数包已经在非推导的上下文中
未推断的上下文是:
- 函数参数包,不会出现在参数声明列表的末尾.
不幸的是,我测试过的编译器(g ++/clang)都没有接受代码.值得注意的是,下面的内容适用于g ++和clang.
template<class... T>
void f(void(*)(nondeduced_t<T>..., char)) {}
Run Code Online (Sandbox Code Playgroud)
而且,这对两者都不起作用:
template<class... …
Run Code Online (Sandbox Code Playgroud) c++ language-lawyer variadic-templates c++11 template-argument-deduction
我有一个std::set
允许从迭代器范围中扣除的东西.
#include <iostream>
#include <set>
int main()
{
std::set s1 = {1,2,3,4};
std::set s2(s1.begin(), s1.end());
}
Run Code Online (Sandbox Code Playgroud)
上述程序未能在GCC中编译.
为什么演绎失败std::set
?
template <typename T> struct A {
A(T);
A(const A&);
};
int main()
{
A x(42); // #1
A y = x; // #2
}
Run Code Online (Sandbox Code Playgroud)
据我了解,T
#1将使用第一个ctor生成的隐式演绎指南推导出.然后x
将使用该ctor初始化.
但是对于#2,T
将使用复制演绎候选人推断(根据我的理解,这是演绎指南的特定情况)(然后y
将使用第二个ctor初始化).
为什么不能T
使用复制版本生成的(隐含)演绎指南来推导#2?
我想我只是不明白复制演绎候选人的一般目的.
c++ templates template-argument-deduction argument-deduction c++17
我希望能够使用新的模板参数推导的地方之一就是构建带有自定义比较器的std::set
's/std::map
s /任何其他容器 - 我的目标是创建一个单行语句,这将创建一个高效的用lambda比较器设置.自C++ 11以来我能做的是:
std::set<int, std::function<bool(int, int)>> s([](int a, int b) {return a > b;});
Run Code Online (Sandbox Code Playgroud)
但由于它使用std::function
,它明显变慢.
另一种选择是:
auto mycomp = [](int a, int b) {return a > b; };
std::set<int, decltype(mycomp)> s(mycomp);
Run Code Online (Sandbox Code Playgroud)
它完成了工作,但1)它需要2行,并创建mycomp
变量2)我需要mycomp
显式传递的类型.
正如我在参考页面上看到的那样,没有一个标准容器有针对这种情况的扣除指南.不幸的是,我担心它甚至无法用当前的语言标准(C++ 17)完成,因为人们可以找到:
仅当不存在模板参数列表时,才会执行类模板参数推导.如果指定了模板参数列表,则不会进行演绎.
这背后的原因是什么?为什么他们不允许部分论证扣除?我想它有些问题我忽略了,但在我看来,它会有所帮助.
c++ templates template-argument-deduction argument-deduction c++17
请考虑以下代码
struct A {
A(int id) : id_ { id } {}
A(const A& rhs) { std::cout << "cctor from " +
std::to_string(rhs.id_) << std::endl; }
A(A&& rhs) { std::cout << "mctor from " +
std::to_string(rhs.id_) << std::endl; }
int id_;
};
template<typename T>
struct B1 {
constexpr B1(T&& x) noexcept : x_ { std::forward<T>(x) } {}
T x_;
};
template<typename T>
struct B2 {
constexpr B2(T&& x) noexcept;
T x_;
};
template<typename T>
constexpr
B2<T>::B2(
T&& x
) noexcept …
Run Code Online (Sandbox Code Playgroud) #include<type_traits>
template <typename T, T>
struct A { };
template <typename T, T t>
void f(A<T, t>) {
}
int main() {
f(A<const int, 0>{});
}
Run Code Online (Sandbox Code Playgroud)
https://godbolt.org/z/n6bcj5rjM
该程序在 C++14 和 C++17 模式下被 GCC 和 ICC 接受,在 C++14 模式下被 Clang 接受,但在 C++17 模式下被 Clang 拒绝,在任一模式下被 MSVC 拒绝。
拒绝是通过这样的诊断:
<source>:12:5: error: no matching function for call to 'f'
f(A<const int, 0>{});
^
<source>:7:6: note: candidate template ignored: deduced conflicting types for parameter 'T' ('const int' vs. 'int')
void f(A<T, t>) {
^ …
Run Code Online (Sandbox Code Playgroud) c++ language-lawyer template-argument-deduction non-type-template-parameter
我发现 Clang、GCC 和 MSVC 之间存在差异,其中 GCC 和 Clang 执行了我所期望的操作:
#include <Eigen/Core>
template <typename Indices, typename T, int Rows> //< Bad
//template <typename Indices, int Rows, typename T> //< OK
//template <typename T, int Rows, typename Indices> //< OK
//template <typename T, typename Indices, int Rows> //< Bad
//template <int Rows, typename Indices, typename T> //< Bad
//template <int Rows, typename T, typename Indices> //< Bad
void f(
const Eigen::Matrix<T, Rows, 1>&,
const Indices&
) {}
int main() {
f(Eigen::Matrix<double, 6, …
Run Code Online (Sandbox Code Playgroud) c++ ×10
template-argument-deduction ×10
c++17 ×5
templates ×4
c++11 ×2
gcc ×2
g++ ×1
non-type-template-parameter ×1
reference ×1
set ×1
std-function ×1
visual-c++ ×1