标签: template-templates

是默认模板模板参数值推导上下文?

我真的很惊讶gcc和clang都接受这个代码:

#include <iostream>
#include <vector>
#include <type_traits>

template <class T, template <class, class = T> class TT, class Y>
T foo(TT<Y>) {
}

int main() {
    static_assert(std::is_same<decltype(foo(std::vector<int>{})), std::allocator<int>>::value);
}
Run Code Online (Sandbox Code Playgroud)

gcc和clang是正确的,默认模板模板参数的值是推导上下文还是编译器扩展?

c++ templates template-templates

8
推荐指数
1
解决办法
142
查看次数

有没有办法将别名模板推导到模板模板参数,同时仍保留其推导上下文的属性

过了一会儿,我再次发现了模板模板参数的强大功能.请参阅以下代码段:

template <template <class> class TT, class T>
void foo(TT<T>) {
}

template <class T>
using typer = T;

int main() {
    foo<typer>(int{});
}
Run Code Online (Sandbox Code Playgroud)

别名模板作为模板模板参数传递给模板,并进一步用于检测模板的其他参数,因为它是推导的上下文.美女!

然而,当需要推断别名模板本身时,看起来编译器会变得疯狂:

template <template <class> class>
struct tag{};

template <template <class> class TT, class T>
void foo(tag<TT>, TT<T>) {
}

template <class T>
using typer = T;

int main() {
    foo(tag<typer>{}, int{});
}
Run Code Online (Sandbox Code Playgroud)

[现场演示]

编译器当然是正确的,TT可以从两者tag<TT>以及TT<T> 参数中推断出来foo,并且int{}模板模板与类型参数模式不匹配.有没有办法保留演绎上下文T但是在TT非演绎语境中TT<T> …

c++ templates template-templates template-aliases

8
推荐指数
1
解决办法
163
查看次数

模板类将自身称为模板模板参数?

这段代码:

template <template <typename> class T>
class A
{
};

template <typename T>
class B
{
    A<B> x;
};
Run Code Online (Sandbox Code Playgroud)

不编译,我想自从A<B>被解释为A<B<T> >B范围内.

那么,你如何B在其范围内作为模板模板参数传递?

c++ templates template-templates

7
推荐指数
1
解决办法
1180
查看次数

有没有理由使模板模板参数不可变?

如果我希望模板模板参数有一个争论,那么我可以声明如下:

template<template<typename> class T>
struct S {
    T<int> t_;
    //other code here
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我以后想要提供一个模板模板参数,该参数需要两个参数,其中第二个具有默认值(如std :: vector)T<int> t_;仍然有效,但模板不匹配template<typename> class T.我可以通过制作template<typename> class T一个可变参数模板模板来解决这个问题template<typename...> class T.现在我的代码更灵活了.

我将来可以将所有模板模板参数变为可变参数吗?有什么理由我不应该(因为其他原因我的代码已经需要C++ 11支持)?

c++ templates template-templates variadic-templates c++11

7
推荐指数
1
解决办法
230
查看次数

模板模板参数的参数是否会导致阴影?

这是合法的C++吗?

template <typename T, template <typename T> class>
struct S { };
Run Code Online (Sandbox Code Playgroud)

Clang(3.7.1)拒绝它,抱怨第一个第二个T阴影T.海湾合作委员会似乎不关心它,我认为这是合理的.我认为只有模板模板参数中重要的参数数量.

c++ templates shadowing template-templates

7
推荐指数
1
解决办法
163
查看次数

Variadic可变参数模板模板参数

是否有一种直接的方法来获得可变参数的可变参数模板模板参数.例如,考虑以下函数签名

template<template<typename,size_t...> class Pack, 
  typename T, size_t ... Args>
void foo(const Pack<T,Args...>& a);
Run Code Online (Sandbox Code Playgroud)

如果我们想要传递两个Packs,我们现在必须做一个重载

template<template<typename,size_t...> class Pack, 
  typename T, size_t ... Args0, size_t ... Args1>
void foo(const Pack<T,Args0...>& a, const Pack<T,Args1...>& b);
Run Code Online (Sandbox Code Playgroud)

现在如果我们想要传递Pack具有不同可变参数的可变数量的对象,例如Args0...,Args1...,Args2....

所以我在想是否有一种切实可行的做法(以下是草图表示).

template<template<typename,size_t...> ... class Pack, typename T,...>  
void foo(const Pack<T,...> ... packs);
Run Code Online (Sandbox Code Playgroud)

c++ variadic-functions template-templates variadic-templates c++11

7
推荐指数
1
解决办法
1112
查看次数

别名模板是否等同于“相同”模板?

上下文

这个问题询问是否可以编写一个可以从给定实例中检索模板的特征。简而言之,问题是:“是否有可能写出f这样f<foo<int>>::typefoo?”

这个答案提出了一些我本来期望的正是那个问题所要求的东西,但答案已经提到它“不完全是”所要求的。

编码

为了查看运行中的代码并理解为什么它被标记为“不完全”,我写了这个:

#include <type_traits>
#include <iostream>

// the template
template <typename T> struct foo {};

// not the template
template <typename T> struct not_foo {};


template <template<class> class A, template<class> class B>
struct is_same_template : std::false_type {};

// this is the questionable part    
template <template<class> class A>
struct is_same_template<A,A> : std::true_type {};

// copied from said answer
template <typename T> struct template_class;

template <template <typename> class C, typename T> …
Run Code Online (Sandbox Code Playgroud)

c++ templates template-templates language-lawyer

7
推荐指数
0
解决办法
58
查看次数

为什么未验证模板模板参数中的概念?

C++20 允许程序为模板模板参数指定概念。例如,

#include <concepts>

template <typename T> concept Char = std::same_as<T, char>;
template <typename> struct S {};
template <template <Char U> typename T, typename U> T<U> foo() { return {}; }

int main() { foo<S, int>(); }
Run Code Online (Sandbox Code Playgroud)

函数的第一个模板参数foo应该是一个单参数模板。

该概念Char仅被定义为 true 类型char,因此尝试满足它 forint将失败。以上程序被所有编译器接受:https : //gcc.godbolt.org/z/PaeETh6GP

能否请您解释一下,为什么可以指定模板模板参数中的概念,但仍然会被忽略?

c++ contravariance template-templates c++-concepts c++20

7
推荐指数
1
解决办法
163
查看次数

部分模板特化中匹配可变参数模板模板参数的精确规则

在为另一个问题创建这个答案时,我遇到了以下问题。考虑这个程序(godbolt):

#include <variant>
#include <iostream>

template <typename T>
struct TypeChecker {
    void operator()() {
        std::cout << "I am other type\n";
    }
};

template<typename... Ts, template<typename...> typename V>
requires std::same_as<V<Ts...>, std::variant<Ts...>>
struct TypeChecker<V<Ts...>>
{
    void operator()()
    {
        std::cout << "I am std::variant\n";
    }
};

int main()
{
    TypeChecker<std::variant<int, float>>{}();
    TypeChecker<int>{}();
}
Run Code Online (Sandbox Code Playgroud)

输出(也是预期的)如下(使用 clang 14.0.0 以及 gcc 12.1):

I am std::variant
I am other type
Run Code Online (Sandbox Code Playgroud)

然而,如果模板的参数列表中的三个点被删除,就像这样(整个程序运行在godbolt上):

template<typename... Ts, template<typename> typename V>
Run Code Online (Sandbox Code Playgroud)

,那么 clang 和 gcc 的输出是不同的。clang …

c++ templates partial-specialization template-templates language-lawyer

7
推荐指数
1
解决办法
257
查看次数

具有引用非类型模板参数的模板是否应该与具有自动非类型模板参数的模板模板参数相匹配?

template<template<auto> class> struct A {};
template<int&> struct B {};

A<B> a;

int main() {}
Run Code Online (Sandbox Code Playgroud)

所有三个编译器 MSVC、GCC 和 Clang 的最新版本都接受此代码 ( https://godbolt.org/z/b7Pv7Ybxv )。但是,auto无法推断出引用类型,那么为什么允许这样做呢?或者编译器在查看标准内容时是否错误地接受了它?


我混淆了上面的参数和参数。我的目的是想问

template<template<int&> class> struct A {};
template<auto> struct B {};

A<B> a;

int main() {}
Run Code Online (Sandbox Code Playgroud)

这也被上述所有编译器所接受。然而,最初的示例也很有趣,因为模板模板参数应该至少与模板参数一样专业,但直观上看起来并不如此。

c++ template-templates language-lawyer auto non-type-template-parameter

7
推荐指数
1
解决办法
276
查看次数