标签: template-specialization

模板化类中模板化成员函数的特化

我有一个带有模板化成员函数的模板化类

template<class T>
class A {
public:
    template<class CT>
    CT function();
};
Run Code Online (Sandbox Code Playgroud)

现在我想以两种方式专门化模板化成员函数.首先是与类相同的类型:

template<class T>
template<>  // Line gcc gives an error for, see below
T A<T>::function<T>() {
    return (T)0.0;
}
Run Code Online (Sandbox Code Playgroud)

类型bool的第二个:

template<class T>
template<>
bool A<T>::function<bool>() {
    return false;
}
Run Code Online (Sandbox Code Playgroud)

这是我试图测试它的方式:

int main() {
    A<double> a;
    bool b = a.function<bool>();
    double d = a.function<double>();
}
Run Code Online (Sandbox Code Playgroud)

现在gcc给了我上面标记的行:

error: invalid explicit specialization before ‘>’ token
error: enclosing class templates are not explicitly specialize
Run Code Online (Sandbox Code Playgroud)

所以gcc告诉我,如果我想专攻功能,我必须专攻A,对吗?我不想这样做,我希望外类的类型是开放的...

最后的答案是:这是不可能的?或者有办法吗?

c++ template-specialization

18
推荐指数
2
解决办法
5128
查看次数

通过static_assert强制执行模板类型

我正在努力了解它的用处static_assert,我想知道它是否可以帮助我执行设计,如果是,那么如何.

我有一个通用的模板类,它在另一个模板类中隐藏它自己的实现,这个类是基于模板类型的大小而部分专用的.以下是此设计的简要概述:

template <class T, size_t S = sizeof(T)>
struct Helper;

template <class T>
struct Helper<T, sizeof(long)>
{
    static T bar();
};

// ... other specializations ...

template <class T>
class Foo
{
public:

    T bar()
    {
        return Helper<T>::bar();
    }
};
Run Code Online (Sandbox Code Playgroud)

美孚如果尺寸仅支持T由一个专业化的支持助手.例如,Foo<long>并且Foo<unsigned long>都受支持.但是,假设用户尝试构造一个Foo<bool>.通常,这会产生错误,因为没有定义Helper for的特化bool,这是预期的行为.

static_assert在此设计中是否有任何方法可以为此界面的用户提供更多有用的错误?

此外,我还想限制用户使用特定类型,即使大小可能是正确的.例如,Foo<float>不应该被允许.现在,我知道强制执行此操作的唯一方法是通过文档中的大胆注释.:)

c++ templates static-assert template-specialization

18
推荐指数
3
解决办法
2万
查看次数

将模板类专门化为结构

我刚刚专门std::hash针对用户定义的类型使用:

template<>
struct hash<...> {...};
Run Code Online (Sandbox Code Playgroud)

当VC10向我发出警告时:

警告C4099:'std :: hash <_Kty>':使用'struct'时首先看到使用'class'看到的类型名称

我发现它的标准库声明std::hashclass,而标准(或我最新的自由草案)声明为struct.

好吧,当然我知道结构与类没有任何不同(除了不同的默认访问和继承类型).但我的问题是:

  1. VC10是否违反此标准,或者是否可以在任何标准库组件中自由交换structs class(当然,只要成员所需的访问类型保持一致)?
  2. 将模板类专门化为结构是否合法,反之亦然,或者这会带来名称解析等问题(至少VC10认为值得警告).

c++ struct class template-specialization

17
推荐指数
1
解决办法
1064
查看次数

实例化错误后的成员函数模板的专业化,以及成员函数的顺序

以下位代码无法在gcc 4.5.3上编译

struct Frobnigator
{
    template<typename T>
    void foo();

    template<typename T>
    void bar(); 
};

template<typename T>
void Frobnigator::bar()
{
}

template<typename T>
void Frobnigator::foo()
{
    bar<T>();
}

template<>      // error
void Frobnigator::foo<bool>()
{
    bar<bool>();
}

template<>
void Frobnigator::bar<bool>()
{
}

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

错误讯息:specialization of ‘void Frobnigator::bar() [with T = bool]’ after instantiation.我终于解决了这个问题,因为Frobnigator::bar<bool>()之前出现了专门化Frobnigator::foo<bool>().显然,方法看起来很重要.

那么为什么以上是上面代码的lite版本,其中bar泛型版本之后出现的特化,有效吗?

struct Frobnigator
{
    template<typename T>
    void foo();
};

template<typename T>
void Frobnigator::bar()
{
}

template<>
void Frobnigator::bar<bool>() …
Run Code Online (Sandbox Code Playgroud)

c++ templates template-specialization

17
推荐指数
2
解决办法
2万
查看次数

C++不同的模板方法调用同一个变量

有人可以解释为什么一次使用方法c(T*)和下一次d<>(int*)?方法cd我似乎完全相同,我无法弄清楚为什么不是同一类型的方法调用.

#include <iostream>
using namespace std;

template<typename T>
void c(T){ cout <<"(T)" << endl; }

template<>
void c<>(int*){ cout <<"(int*)" << endl; }

template<typename T>
void c(T*){ cout <<"(T*)" << endl; }

template<typename T>
void d(T){ cout <<"(T)" << endl; }

template<typename T>
void d(T*){ cout <<"(T*)" << endl; }

template<>
void d<>(int*){ cout <<"(int*)" << endl; }

int main(){
    int i;
    c(&i);
    d(&i);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

(T*)
(int*)
Run Code Online (Sandbox Code Playgroud)

c++ templates template-specialization

17
推荐指数
2
解决办法
570
查看次数

嵌套类模板专门化

一类:

template<typename C, typename T>
class A
{
    template <typename U>
    class Nested{};

    Nested<T> n;
};
Run Code Online (Sandbox Code Playgroud)

我想专攻Nested.这是我尝试过的:

template<typename C, typename T>
class A
{
    template <typename U>
    class Nested{};

    template <>
    class Nested<int>{}; // by my logic this should work by I have a compilation error "explicit specialization in non-namespace scope 'class A<C, T>'"

    Nested<T> n;
};
Run Code Online (Sandbox Code Playgroud)

我的下一次尝试:

template<typename C, typename T>
class A
{
    template <typename U>
    class Nested{};

    Nested<T> n;
};

template<>
A<>::Nested<int>{}; // What is …
Run Code Online (Sandbox Code Playgroud)

c++ templates template-specialization

17
推荐指数
1
解决办法
4118
查看次数

删除"常规"情况的专用模板函数无法使用g ++ <= 4.8.0和clang ++进行编译

使用旧版本的g ++(4.8.0,MinGW)编译项目我发现此代码无法编译:

template<typename T>
void foo() = delete;

template<>
void foo<int>(){}

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

似乎g ++甚至没有尝试寻找显式特化,如果它看到基本情况被删除.

mitalia@mitalia:~/scratch$ /opt/mingw32-dw2/bin/i686-w64-mingw32-g++ -std=c++11 buggy_deleted_template.cpp 
buggy_deleted_template.cpp: In function 'int main()':
buggy_deleted_template.cpp:8:14: error: use of deleted function 'void foo() [with T = int]'
     foo<int>();
              ^
buggy_deleted_template.cpp:5:6: error: declared here
 void foo<int>(){}
      ^
mitalia@mitalia:~/scratch$ /opt/mingw32-dw2/bin/i686-w64-mingw32-g++ --version 
i686-w64-mingw32-g++ (rubenvb-4.8.0) 4.8.0
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for …
Run Code Online (Sandbox Code Playgroud)

c++ templates template-specialization deleted-functions c++11

17
推荐指数
1
解决办法
1804
查看次数

可变参数模板模板参数可以是部分专用的吗?

考虑以下程序:

template<template<typename ...> class>
struct foo {};

template<template<typename> class C>
struct foo<C> {};

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

Clang拒绝了它的错误:

类模板部分特化不会专门化任何模板参数

即使在最新的clang 7.0 HEAD中,请参见此处的演示.但是,gcc接受了它.

请参阅[temp.class.spec],其中陈述了部分特化的规则,我找不到任何禁止该模板的部分特化的东西.特别是,专业化确实更专业,错误消息看起来不正确.

编辑:

但是,gcc的行为也是异常的,请考虑以下程序:

#include <iostream>

template<template<typename ...> class>
struct foo { void show() { std::cout << "Primary.\n"; } };

template<template<typename> class C>
struct foo<C> { void show() { std::cout << "Specialized.\n"; } };

template<class...> struct bar {};

int main() {
    foo<bar> f;
    f.show();
}
Run Code Online (Sandbox Code Playgroud)

事实证明,gcc在这种情况下使用专用版本,请参见此处.

现在我想问:

  • 是标准允许的这种局部专业化吗?

  • 哪个编译器是正确的?(一个/全部/没有?)

c++ templates clang template-specialization language-lawyer

17
推荐指数
1
解决办法
575
查看次数

C++20 后友元声明中的模板特化

上下文:令我们惊讶的是,启用 C++20 模式和两阶段合规性的 MSVC 接受以下代码:

\n
template<class T>\nclass X\n{\n    friend int foo<X>(X x);\n\n    int a = 10;\n};\n\ntemplate <class T>\nint foo(T t)\n{\n    return t.a;\n}\n\nint main()\n{\n    return foo(X<float>{});\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这会编译/链接并10在 MSVC 和 gcc 中返回(但会发出 clang 声): https: //godbolt.org/z/98cd7v7a6

\n

那些了解两阶段查找的人会发现这看起来非常疯狂 - 我们可以在声明相应的模板之前以某种方式与模板专门化成为朋友。看起来和听起来都很不对劲。事实上,对于早期的 C++ 版本,所有编译器都会立即拒绝它: https: //godbolt.org/z/M1733EPd5

\n

但 C++20 中的以下措辞似乎为此铺平了道路(或者至少使其从一开始就不是完全错误的):https://timsong-cpp.github.io/cppwp/n4861/temp .names#2.sentence-4(强调我的)

\n
\n

如果名称是一个 unqualified-id 后跟一个名称,则该名称也被视为引用模板,并且<名称查找要么找到一个或多个函数,要么什么也没找到

\n
\n

现在,这导致了一大堆……好吧,荒谬的极端情况。请注意,在声明之外,friend您必须以 开始模板专门化template<>,但声明中的情况并非如此friend。可以预见的是,编译器甚至无法就现在合法和不合法的内容达成一致:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
交朋友...神箭 …

c++ friend template-specialization language-lawyer c++20

17
推荐指数
2
解决办法
337
查看次数

专门针对最小参数数量的可变参数模板模板参数:合法与否?

我有代码:

#include <cstdio>

template<template<typename...> class>
struct Foo 
{ 
    enum { n = 77 };
};

template<template<typename, typename...> class C>
struct Foo<C>
{
    enum { n = 99 }; 
};

template<typename...> struct A { };

template<typename, typename...> struct B { };

int main(int, char**)
{
    printf("%d\n", Foo<A>::n);
    printf("%d\n", Foo<B>::n);
}
Run Code Online (Sandbox Code Playgroud)

这个想法是它template<typename, typename...> class的一个子集template<typename...> class,因此有可能专注于它.但它非常深奥,所以也许不是.我们来试试吧.

GCC 4.7说:

$ g++ -std=c++11 test157.cpp 
Run Code Online (Sandbox Code Playgroud)

它汇编了!

运行它:

$ ./a.out 
77
99
Run Code Online (Sandbox Code Playgroud)

有用!

Clang 3.1说:

$ clang++ -std=c++11 test157.cpp
test157.cpp:10:8: error: class template …
Run Code Online (Sandbox Code Playgroud)

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

16
推荐指数
1
解决办法
2133
查看次数