我有以下模板函数,它具有模板模板参数作为其参数。
template<typename T,
template <typename... ELEM> class CONTAINER = std::vector>
void merge(typename CONTAINER<T>::iterator it )
{
std::cout << *it << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
以下代码使用此代码。
std::vector<int> vector1{1,2,3};
merge<int>(begin(vector1));
Run Code Online (Sandbox Code Playgroud)
它按预期工作,但是当我使用
merge(begin(vector1));
Run Code Online (Sandbox Code Playgroud)
无法推断出的类型T。
我认为它可以从std::vector<int>::iterator it;as 推断出类型int。
为什么编译器无法推断类型?
c++ templates template-templates template-argument-deduction c++14
是.
假设我有一个包含typedef的简单可变结构:
template<typename... TArgs> struct TupleTypeHolder {
using TupleType = std::tuple<TArgs*...>;
};
Run Code Online (Sandbox Code Playgroud)
我想将TupleTypeHolder<something>模板参数传递给另一个类,并获取该typedef.
我的所有尝试都没有编译.
// None of these is valid
template<template<typename...> class TTupleTypeHolder> struct TupleMaker {
using MyTupleType = TTupleTypeHolder::TupleType; // Not valid
using MyTupleType = typename TTupleTypeHolder::TupleType; // Not valid
};
template<template<typename... A> class TTupleTypeHolder> struct TupleMaker2 {
// A is not a valid name here
using MyTupleType = TTupleTypeHolder<A...>::TupleType; // Not valid
using MyTupleType = typename TTupleTypeHolder<A...>::TupleType; // Not valid
};
Run Code Online (Sandbox Code Playgroud)
有没有办法使用可变参数模板类的可变参数模板参数(在本例中为TupleTypeHolders TArgs...)来自使用上述类作为模板可变参数模板参数的类? …
正如以下代码片段中的注释所说,这是 gcc 4.4 的解决方法。错误,我现在可能应该删除它。有关此背景的信息,请参阅带有 gcc 4.4 的模板模板参数和可变参数模板。
在任何情况下,这都会在带有 clang 3.4.2-4 的 Debian Wheezy 上出现错误,从不稳定向后移植。这适用于 gcc 4.9,也从 Debian Wheezy 上的不稳定(和 4.7)向后移植。
// Workaround for gcc 4.4 bug. See /sf/ask/596024341/
template <typename S, typename T,
template <typename S, typename T, typename... Args> class C,
typename... Args>
struct maptype
{
typedef C<S, T, Args...> type;
};
int main(void){}
Run Code Online (Sandbox Code Playgroud)
错误是
clang++ -o shadow.ocl -c -ftemplate-depth-100 -fno-strict-aliasing -fno-common -ansi -Wextra -Wall -Werror -Wno-unused-function -Wc++0x-compat -Wpointer-arith -Wcast-qual -Wcast-align -std=c++11 -mtune=native -msse3 -O3 shadow.cc
shadow.cc:3:23: …Run Code Online (Sandbox Code Playgroud) 最小的例子:
template<template<class ...> class>
struct templ {};
template<class T>
using special = templ<T::type>;
int main() {}
Run Code Online (Sandbox Code Playgroud)
铛++:
test.cpp:5:23: error: template argument for template template parameter must be a class template or type alias template
using special = templ<T::type>;
Run Code Online (Sandbox Code Playgroud)
实际上,我的意思是说这T::type是一个类模板,例如
struct detail1 {
template <class T>
using type = std::vector<T>;
};
struct detail2 {
template <class T>
struct type {};
};
Run Code Online (Sandbox Code Playgroud)
但是怎么能这么说呢?g ++建议使用typename T::type,但这对我来说是错误的,事实上,这并不能解决错误.
我正在尝试编写一个Bind元编程模板辅助元函数,它将模板参数绑定到某个东西上.
我有一个简单模板元函数的工作实现:
template<typename T0, typename T1>
struct MakePair
{
using type = std::pair<T0, T1>;
};
template<template<typename...> class TF, typename... Ts>
struct Bind
{
template<typename... TArgs>
using type = TF<Ts..., TArgs...>;
};
using PairWithInt = typename Bind<MakePair, int>::type;
static_assert(std::is_same<PairWithInt<float>, MakePair<int, float>>{}, "");
Run Code Online (Sandbox Code Playgroud)
但是,如果MakePair模板参数是模板模板呢?还是简单的数值?
template<template<typename> class T0, template<typename> class T1>
struct MakePair0
{
using type = /*...*/;
};
template<template<typename...> class TF, template<typename> class... Ts>
struct Bind0 { /*...*/ }
// ...
template<int T0, int T1>
struct MakePair1
{ …Run Code Online (Sandbox Code Playgroud) 厌倦了"统一初始化"并不是非常统一,我决定编写一个通用construct()包装器,如果类型是聚合,则使用聚合初始化,否则直接初始化:
template <class T, class... Args,
std::enable_if_t<std::is_aggregate_v<T>, int> = 0>
constexpr auto construct(Args&&... args)
-> decltype(T{std::forward<Args>(args)...})
{
return T{std::forward<Args>(args)...};
}
template <class T, class... Args>
constexpr auto construct(Args&&... args)
-> decltype(T(std::forward<Args>(args)...))
{
return T(std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)
这很好用:
template <class T, class U>
struct my_pair { T first; U second; };
auto p = construct<my_pair<int, float>>(1, 3.14f);
auto v = construct<std::vector<int>>(5, 0);
Run Code Online (Sandbox Code Playgroud)
我想扩展它以使用模板参数推导为构造函数.所以我添加了另一对重载:
template <template <class...> class T, // <-- (1)
class... Args,
class A = decltype(T{std::declval<Args>()...}),
std::enable_if_t<std::is_aggregate_v<A>, int> = …Run Code Online (Sandbox Code Playgroud) 从奇怪的递归模板模式(CRTP)模板-模板基类继承构造函数的语法是什么?
template<typename T, template<typename> typename U>
struct Base {
Base(int) { }
};
template<typename T>
struct Derived : public Base<T, Derived> {
using Base<T, Derived>::Base;
};
int main(int argc, char *argv[]) {
Derived<double> foo(4);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在VS2019中,上述代码会出现以下错误:
错误 C3210: 'Base<double, Derived<double> >': 成员 using-declaration 只能应用于基类成员
错误 C3881: 只能从直接基类继承构造函数
使上述代码正常工作所需的语法是什么?
当我在玩的时候,我偶然发现了下面的代码片段,令人惊讶的是,它与我的期望不符。
#include <tuple>
#include <type_traits>
template <class... Ts>
using myTuple = std::tuple<Ts...>;
template <template <class...> class Lhs, template <class...> class Rhs>
struct is_same
: public std::false_type
{};
template <template <class...> class T>
struct is_same<T, T>
: public std::true_type
{};
int main() {
static_assert(is_same<myTuple, std::tuple>::value, "not same");
}
Run Code Online (Sandbox Code Playgroud)
我把它放在godbolt上并尝试用 3 个不同的编译器(clang、msvc 和 gcc)编译它,并收到了混合的结果。
铛:
<source>:18:5: error: static_assert failed due to requirement 'is_same<myTuple, std::tuple>::value' "not same"
static_assert(is_same<myTuple, std::tuple>::value, "not same");
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
微软VC:
<source>(18): error C2338: static_assert failed: 'not same' …Run Code Online (Sandbox Code Playgroud) 好吧,所以我写了一个类似stl的算法cartesian_product.对于那些不知道的人来说,笛卡尔积是两组中每一对可能的元素.所以笛卡尔乘积{1, 2, 3}和{10, 20, 30}是
{(1,10), (1,20), (1,30), (2,10), (2,20), (2,30), (3,10), (3,20), (3,30)}
所以功能看起来像
template <typename InIt1, typename InIt2, typename OutIt>
void
cartesian_product(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt out)
{
for (; first1 != last1; ++first1)
for (InIt2 it = first2; it != last2; ++it)
*out++ = std::make_pair(*first1, *it);
}
Run Code Online (Sandbox Code Playgroud)
没有模板typedef,所以我创建了一个traits类来保存输出迭代器来自的类型:
template <typename ObjA, typename ObjB, template <typename> class Container>
struct cartesian_product_traits
{
typedef Container<std::pair<ObjA, ObjB> > type;
};
Run Code Online (Sandbox Code Playgroud)
那么我可以说: …
由于可变参数模板,我前一段时间实现了C++等效的Python链函数.该函数用于连续迭代许多容器.这是使用名为的生成器的函数的旧工作版本ChainedObject,无论它是什么:
template<typename... Iterables>
auto chain(Iterables&&... iters)
-> ChainObject<Iterables...>
{
return /* ... */;
}
Run Code Online (Sandbox Code Playgroud)
相应的主要内容:
int main()
{
std::vector<int> vec = { 1, 2, 3, 4, 5 };
std::list<int> li = { 6, 7, 8, 9, 10, 11, 12, 13 };
for (auto& i: chain(vec, li))
{
// You can edit a range of iterables
// as if there was only one of them.
i *= 5;
std::cout << i << std::endl;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
那个主要工作正常.我们不关心ChainObject中的问题,所以让我们看看它.我尝试使用模板模板来确保使用的不同集合具有相同value_type …