假设我有一个模板(称为ExampleTemplate),它带有两个参数:容器类型(例如list,vector)和包含的类型(例如float,bool等).由于容器实际上是模板,因此该模板具有模板参数.这是我必须写的:
#include <vector>
#include <list>
using namespace std;
template < template <class,class> class C, typename T>
class ExampleTemplate {
C<T,allocator<T> > items;
public:
....
};
main()
{
ExampleTemplate<list,int> a;
ExampleTemplate<vector,float> b;
}
Run Code Online (Sandbox Code Playgroud)
你可能会问什么是"分配器"的事情.好吧,最初,我尝试了显而易见的事情......
template < template <class> class C, typename T>
class ExampleTemplate {
C<T> items;
};
Run Code Online (Sandbox Code Playgroud)
...但遗憾的是我发现了分配器的默认参数......
vector<T, Alloc>
list<T, Alloc>
etc
Run Code Online (Sandbox Code Playgroud)
...必须在模板声明中明确地"保留".正如您所看到的,这会使代码变得更加丑陋,并迫使我重现模板参数的默认值(在本例中为分配器).
哪个是坏的.
编辑:问题不是关于容器的具体问题 - 它是关于"模板参数模板中的默认值",以上只是一个例子.答案取决于STL容器具有":: value_type"的知识不是我所追求的.想想一般问题:如果我需要在模板ExampleTemplate中使用模板参数C,那么在ExampleTemplate的主体中,我是否必须在使用它时重现C的默认参数?如果必须,那不会引入不必要的重复和其他问题(在这种情况下,C是STL容器,可移植性问题 - 例如"allocator")?
Gcc和clang似乎不同意这段代码是否应该编译:
#include <type_traits>
template <typename Signature, int N = 0>
struct MyDelegate { };
template <typename D>
struct signature_traits;
template <template <typename> class Delegate, typename Signature>
struct signature_traits<Delegate<Signature>>
{
using type = Signature;
};
static_assert(std::is_same_v<
void(int, int),
signature_traits<MyDelegate<void(int, int)>>::type
>);
Run Code Online (Sandbox Code Playgroud)
在这里查看godbolt输出并尝试一下.我在这里支持clang,但是C++标准对此有何看法?
一个后续问题 - 这可以用于铿锵声吗?
c++ templates language-lawyer template-meta-programming c++17
在探索这个答案的过程中,我发现需要参数包的模板不会被需要具有特定参数数量的模板的模板所接受.
在我看来,这是一个缺陷,因为如果模板可以采用任意数量的参数,它应该能够映射到特定的数字.是否有语言律师可以解释为什么不允许这样做?
这是一个简单的例子:
template <typename...Ts>
using pack = void;
template <template <typename> class>
using accept_template = int;
accept_template<pack> value = 0;
Run Code Online (Sandbox Code Playgroud)
当然,我不会在这个确切的场景中使用它.它将用于将模板传递给另一个模板,该模板将以某种方式使用传递的模板.在我链接的答案中,我已经说明了一种解决方法,但我仍然认为这是一个缺陷.
我发现以下一段代码:
#include <iostream>
#include <vector>
template <typename T>
struct X : std::false_type {};
template <template <typename> class Y, typename U>
struct X<Y<U>> : std::true_type {};
int main() {
if (X<int>())
std::cout << "wrong\n";
if (X<std::vector<double>>())
std::cout << "correct\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
仅correct在使用g++-7with 编译时打印-std=c++1z.其它版本g++,clang++或者其他std标志不能产生正确的.
这是当前实现的错误,并且此代码不应该打印任何内容,或者是否在C++ 17中发生了变化,这使得此代码按预期工作?
在帮助解决模板模板参数中太多模板参数中出现的问题时,我脑子里出现了一个问题:在这种情况下,哪个编译器对编译是正确的:
template <template <typename, typename> class Op>
class Function
{
};
template <typename A, typename B, bool is_f = std::is_floating_point<A>::value || std::is_floating_point<B>::value > struct Operator;
template <typename A, typename B>
struct Operator<A, B, false>
{};
template <typename A, typename B>
struct Operator<A, B, true>
{};
using FunctionOperator = Function<Operator>;
int main(int argc, char * argv[]){
std::cout << "hi!\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
GCC 7+编译它没有错误.Clang 6及更高版本给出错误,表明Operator模板作为模板参数传递时出现问题:
tmp.cpp:19:35: error: template argument has different template parameters than its …Run Code Online (Sandbox Code Playgroud) 这段代码:
#include <memory>
template <template <typename> class Ptr>
class A { Ptr<int> ints; };
using B = A<std::unique_ptr>;
Run Code Online (Sandbox Code Playgroud)
产生以下错误(使用GCC 6.3):
a.cpp:6:28: error: type/value mismatch at argument 1 in template parameter list for ‘template<template<class> class Ptr> class A’
using B = A<std::unique_ptr>;
^
a.cpp:6:28: note: expected a template of type ‘template<class> class Ptr’, got ‘template<class _Tp, class _Dp> class std::unique_ptr’
Run Code Online (Sandbox Code Playgroud)
现在,我可以解决这个问题,就像这样:
template <typename T>
using plugged_unique_ptr = std::unique_ptr<T>;
using B = A<plugged_unique_ptr>;
Run Code Online (Sandbox Code Playgroud)
但为什么我要这样做?我的意思是,为什么编译器不愿意"插入"第二个模板参数std::unique_ptr及其默认值并允许std::unique_ptr用作模板参数A?
c++ unique-ptr template-templates c++11 template-argument-deduction
请考虑以下代码,该代码使用"模板模板"参数来使用多种类型实例化类模板:
#include <iostream>
using namespace std;
enum E
{
a = 0,
b = 1
};
template <template <E> class Action, class T>
void do_something(const T& value)
{
typedef Action<a> type1;
typedef Action<b> type2;
}
template <E e, class Enable = void>
class Foo
{
};
int main()
{
do_something<Foo>(int(55));
}
Run Code Online (Sandbox Code Playgroud)
使用较旧的编译器(GCC 4.1.2),上面的代码编译得很好.但是,使用较新的编译器(GCC 4.4.6或4.8.1),会产生以下错误:
test3.cpp:25:27: error: no matching function for call to ‘do_something(int)’
do_something<Foo>(int(55));
Run Code Online (Sandbox Code Playgroud)
所以它看起来像GCC无法绑定do_something,因为模板模板参数只声明一个参数(一个枚举),但是Foo实际上需要两个模板参数(即使一个是默认值.)我猜GCC 4.1.2允许默认参数被忽略.
好的,如果我将模板定义更改为:
template <template <E, class> class Action, class T>
void …Run Code Online (Sandbox Code Playgroud) 我有一些类型特征SomeTraits,可以T通过 从中提取类型是否满足某些条件SomeTraits<T>::value。如何检查给定的所有类型std::tuple<>并检查(通过静态断言)它们是否都满足上述条件?例如
using MyTypes = std::tuple<T1, T2, T3>;
// Need some way to do something like
static_assert(SomeTupleTraits<MyTypes>::value, "MyTypes must be a tuple that blabla...");
Run Code Online (Sandbox Code Playgroud)
在哪里SomeTupleTraits检查SomeTraits<T>::value == true里面的每种类型是否MyTypes?
我仅限于 C++14。
我正在尝试制作"复合"模板类型.像这样的东西
template <typename A, typename T>
class configurator
{
public:
configurator(const A<T> & adapter) : m_adapter(adapter) {}
private:
A<T> m_adapter;
};
Run Code Online (Sandbox Code Playgroud)
编译器抱怨
error: expected ')'
configurator(const A<T> & adapter
^
Run Code Online (Sandbox Code Playgroud)
为什么这不起作用?它可以使它工作吗?
c++ ×9
templates ×6
c++11 ×2
c++14 ×2
c++17 ×2
clang++ ×1
g++ ×1
template-argument-deduction ×1
tuples ×1
type-traits ×1
unique-ptr ×1