如果我有一个普通(弱)枚举,我可以使用它的枚举值作为非类型模板参数,如下所示:
enum { Cat, Dog, Horse };
template <int Val, typename T> bool magic(T &t)
{
return magical_traits<Val>::invoke(t);
}
Run Code Online (Sandbox Code Playgroud)
并称之为: magic<Cat>(t)
据我所知,如果我有一个强类型的枚举,并且不想硬编码枚举类型,我最终得到:
enum class Animal { Cat, Dog, Horse };
template <typename EnumClass, EnumClass EnumVal, typename T> bool magic(T &t)
{
return magical_traits<EnumVal>::invoke(t);
}
Run Code Online (Sandbox Code Playgroud)
现在我得写:magic<Animal, Animal::Cat>(t)
这似乎是多余的.
有没有办法避免输入枚举类和值,缺少
#define MAGIC(E, T) (magic<decltype(E), E>(T));
Run Code Online (Sandbox Code Playgroud) c++ templates strong-typing template-argument-deduction c++17
我阅读了有关std::vector
使用cppreference的演绎指南.
例:
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3, 4};
std::vector x{v.begin(), v.end()}; // uses explicit deduction guide
}
Run Code Online (Sandbox Code Playgroud)
所以,我有一些问题:
什么是std::vector
C++ 17 中的演绎指南?
为什么以及何时需要向量推导?
在这里,是x
一个std::vector<int>
还是一个std::vector<std::vector<int>>
?
在阅读另一个问题时,我遇到了部分排序问题,我将其缩减为以下测试用例
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
我有一个重载的模板函数:
template<typename T1, typename T2>
auto overMax(T1 a, T2 b)
{
std::cout << __FUNCSIG__ << std::endl;
return b < a ? a : b;
}
template<typename RT, typename T1, typename T2>
RT overMax(T1 a, T2 b)
{
std::cout << __FUNCSIG__ << std::endl;
return b < a ? a : b;
}
Run Code Online (Sandbox Code Playgroud)
如果我这样称呼它:
auto a = overMax(4, 7.2); // uses first template
auto b = overMax<double>(4, 7.2); // uses second template
Run Code Online (Sandbox Code Playgroud)
一切都很完美,但是
auto c = overMax<int>(4, 7.2); // error
Run Code Online (Sandbox Code Playgroud)
导致模棱两可的调用。
为什么 …
c++ templates template-argument-deduction c++17 visual-studio-2019
我正在研究自C++ 17以来可用的类模板推导.以下是我想问的代码:
#include <iostream>
#include <cmath>
using std::endl;
using std::cout;
template<typename T>
struct MyAbs {
template<typename U>
MyAbs(U&& u) : t(std::forward<T>(u))
{ cout << "template" << endl;}
#ifdef ON
MyAbs(const T& t) : t(t) {}
#endif
T operator()() const
{
return std::abs(t);
}
T t;
};
/*
// may need the following
template<typename U>
MyAbs(U&&) -> MyAbs<typename std::remove_reference<U>::type>;
*/
int main()
{
const double d = 3.14;
cout << MyAbs(4.7)() << endl;
cout << MyAbs(d)() << endl;
return 0;
} …
Run Code Online (Sandbox Code Playgroud) 我理解,给定一个支撑的初始化程序,auto
将推导出一种类型std::initializer_list
,而模板类型推导将失败:
auto var = { 1, 2, 3 }; // type deduced as std::initializer_list<int>
template<class T> void f(T parameter);
f({ 1, 2, 3 }); // doesn't compile; type deduction fails
Run Code Online (Sandbox Code Playgroud)
我甚至知道在C++ 11标准中指定的位置:14.8.2.5/5 bullet 5:
[如果程序有,则这是一个非推导的上下文]一个函数参数,其关联参数是初始化列表(8.5.4),但参数没有std :: initializer_list或者可能是cv-qualified std :: initializer_list的引用类型.[ 例如:
模板void g(T);
克({1,2,3}); //错误:没有推断T的参数
- 结束例子 ]
我不知道或不理解的是为什么存在这种类型演绎行为的差异.C++ 14 CD中的规范与C++ 11中的规范相同,因此标准化委员会可能不会将C++ 11行为视为缺陷.
有人知道为什么auto
推导出支撑初始值设定项的类型,但是不允许使用模板吗?虽然对"这可能是原因"形式的推测性解释很有意思,但我对那些知道为什么标准是按原样编写的人的解释特别感兴趣.
c++ templates c++11 list-initialization template-argument-deduction
我声明了两个模板,第一个将参数x
从type 转换T
为type U
,第二个从type转换U
为type T
.如果我cast
用10 调用,编译器不会抱怨.我认为两者都符合要求使用,因此应该有歧义,这是真的吗?此代码打印10.
#include <iostream>
template<typename T, typename U>
U cast(T x) {
return static_cast<U>(x);
}
template<typename T, typename U>
T cast(U x) {
return static_cast<T>(x);
}
int main() {
std::cout << cast<int,float>(10) << '\n';
}
Run Code Online (Sandbox Code Playgroud) c++ templates overload-resolution template-argument-deduction
考虑以下代码:
template <typename>
struct S { };
void g(S<int> t);
template <typename T>
void f(T, std::function<void(S<T>)>);
Run Code Online (Sandbox Code Playgroud)
尝试调用时
f(0, g);
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
Run Code Online (Sandbox Code Playgroud)error: no matching function for call to 'f' f(0, g); ^ note: candidate template ignored: could not match 'function<void (S<type-parameter-0-0>)>' against 'void (*)(S<int>)' void f(T, std::function<void(S<T>)>); ^
While I understand that generally the type of the std::function
parameter can't be deduced as it is a non-deduced context
In this case T
can first be deduced by the passed argument …
c++ templates language-lawyer c++11 template-argument-deduction
假设我有一些类型的对象T
,我想把它放到一个引用包装器中:
int a = 5, b = 7;
std::reference_wrapper<int> p(a), q(b); // or "auto p = std::ref(a)"
Run Code Online (Sandbox Code Playgroud)
现在我可以很容易地说if (p < q)
,因为引用包装器已转换为其包装类型.一切都很开心,我可以处理一组参考包装器,就像它们是原始对象一样.
(正如下面链接的问题所示,这可以是生成现有集合的备用视图的有用方法,可以随意重新排列,而不会产生完整副本的成本,以及维护原始集合的更新完整性. )
但是,对于某些类,这不起作用:
std::string s1 = "hello", s2 = "world";
std::reference_wrapper<std::string> t1(s1), t2(s2);
return t1 < t2; // ERROR
Run Code Online (Sandbox Code Playgroud)
我的解决方法是在这个答案中定义一个谓词*; 但我的问题是:
为什么以及何时可以将运算符应用于引用包装器并透明地使用包装类型的运算符?为什么会失败std::string
?它与std::string
模板实例的事实有什么关系?
*)更新:根据答案,似乎使用std::less<T>()
是一般解决方案.
c++ templates implicit-conversion reference-wrapper template-argument-deduction
请考虑以下代码:
template <typename... Types>
struct list
{
template <typename... Args>
list(Args...)
{
static_assert(sizeof...(Types) > 0);
}
};
template <typename... Args>
list(Args...) -> list<Args...>;
int main()
{
list l{0, 0.1, 'a'};
}
Run Code Online (Sandbox Code Playgroud)
我希望decltype(l)
如此list<int, double, char>
.不幸的是,g ++ 7.2和g ++ trunk失败了静态断言.clang ++ 5.0.0和clang ++ trunk编译并按预期工作.
这是一个g ++错误吗?或者,为什么不应该遵循演绎指南?
在构造函数上添加SFINAE约束似乎提供了所需的行为:
template <typename... Args,
typename = std::enable_if_t<sizeof...(Args) == sizeof...(Types)>>
list(Args...)
{
static_assert(sizeof...(Types) > 0);
}
Run Code Online (Sandbox Code Playgroud)
c++ templates variadic-templates template-argument-deduction c++17