当前位置: 首页 > 知识库问答 >
问题:

专门化自动跟踪返回类型

刘丰羽
2023-03-14

我有一些代码使用两种不同类型的颜色,每个通道8位和每个通道16位,每个都由一个结构表示。为了有效地重用我的代码,我有一个模板函数可以对它们进行一些渲染。因此,我希望有一个模板函数来获取我的颜色通道的最大值。

我最初的尝试是这样的。我只展示了8 bpc的专业化

struct Pixel8
{
   unsigned char r;
   unsigned char g;
   unsigned char b;
};
#define PIXEL8_MAX 255

template <class PIXEL>
auto getMax( ) -> decltype( PIXEL::r )
{
   static_assert( sizeof(PIXEL) > 0, "getMax can only be called with a pixel type." );
}
template <>
auto getMax<Pixel8>( ) -> decltype( Pixel8::r )
{
   return PIXEL8_MAX;
}

这不会在Visual studio 2012中编译。我明白了

1个

对我来说,我觉得这应该行得通,但我一直找不到任何例子。在Specialize函数模板中还有一个类似的问题,decltype后面有一个返回类型,但在这里,每个专门化的返回类型都是相同的。

我找到了一个解决方法,我会将其作为答案发布,以便其他人可以受益。但是它不是很透明,所以如果有人可以告诉我上面的代码是否有效,这是VC不兼容,或者如果它无效,那么为什么以及如何使其有效?

共有3个答案

柳灿
2023-03-14

使用宏定义常量,如本题代码中所示

#define PIXEL8_MAX 255

…并不理想。

此外,定义与使用的类型冲突。char不能保证具有该最大值,并且在大多数实现中,默认情况下不会具有该最大值。您可以将字节类型定义为无符号字符,但即使如此,也不能保证8位,应该检查它。

标准库提供了numeric_limits类模板来处理最大值等:

#include <limits>       // std::numeric_limits

#define STATIC_ASSERT( e ) static_assert( e, #e )

using Byte = unsigned char;
int const bits_per_byte = std::numeric_limits<Byte>::digits;
STATIC_ASSERT( bits_per_byte == 8 );

struct Pixel8
{
    Byte r;
    Byte g;
    Byte b;
};

template< class Pixel >
constexpr auto getMax() -> decltype( Pixel::r )
{
    return std::numeric_limits<decltype( Pixel::r )>::max();
}

#include <iostream>
using namespace std;

auto main() -> int
{
    cout << +getMax<Pixel8>() << endl;
}
马阳晖
2023-03-14

这是获取所需行为的解决方法。它依赖于这样一个事实,即有另一种方法可以在不使用dectype的情况下在C中定义类型。这是使用typname。

它在这种情况下的主要用途如下,想象两个类和两个函数

class MyClass
{
public:
    class MyThing
    {
    };
};

class MyOtherClass
{
public:
    static int MyThing;
}

template< class T >
void func1( T something )
{
    typename T::MyThing thing;
}

template< class T >
void func2( T something )
{
    T::MyThing = 5;
}

如果我们将其中一个类作为模板参数T传递,那么T::MyThing将是MyClass的类型,而My另类则是静态int。它们完全不兼容,因此我们使用typename来分隔它们。在函数1中,我们使用typename来声明T::MyThing是一种类型。我们可以传入MyClass对象。在函数2中,我们省略了typename,因此T::MyThing被解释为一个变量,我们可以传入My另类。没有typename,就无法判断T::MyThing是类型还是静态变量。

还请注意,typename可以引用typedef以及内部类,因此,如果我们创建一个模板类或结构,其中包含类型的typedef,我们可以使用typename访问该类型。

template<class PIXEL>
struct pixTypes
{
};

template<>
struct pixTypes<Pixel8>
{
    typedef char type;
};

template <class PIXEL>
auto getMax( ) -> typename pixTypes<PIXEL>::type
{
    static_assert( false, "getMax can only be called with a pixel type." );
}
template <>
auto getMax<Pixel8>() -> typename pixTypes<Pixel8>::type
{
    return PIXEL8_MAX;
}

因此,现在我们从typename中获取返回类型,该typename引用专门模板结构中的typedef。

这似乎是围绕一切的一种相当复杂的方式,但它确实可以在Visual Studio 12上编译

尤博达
2023-03-14

尝试使返回类型取决于模板参数类型:

struct Pixel8
{
    char r;
    char g;
    char b;
};

template<typename T>
struct ColourType
{
    typedef decltype(T::r) type;
};

#define PIXEL8_MAX 255

template <class PIXEL>
typename ColourType<PIXEL>::type getMax()
{
    static_assert(false, "getMax can only be called with a pixel type.");
}
template <>
ColourType<Pixel8>::type getMax<Pixel8>()
{
    return PIXEL8_MAX;
}
 类似资料:
  • 我们不允许寻求书籍、工具、软件库等推荐的问题。你可以编辑这个问题,以便用事实和引用来回答。 是否可以跟踪您是否正在使用自动化工具自动执行任务? 有人能回答我的问题吗?

  • 考虑代码: 我用不同的编译器(通过编译器资源管理器)测试了代码。 如果Clang 7.0.0编译,而给出错误: :8:20:错误:没有与函数模板专用化“栏”匹配的函数模板 :7:26:注意:已忽略候选模板:无法将'void()'与'int()'匹配 Visual C同意(MSVC 19 2017 RTW): (8) :错误C2912:显式专门化“int Test::bar(void)”不是函数模板

  • 我想编写一个函数模板,它返回各种类型的随机变量(bool、char、short、int、float、double,以及这些变量的无符号版本)。 我看不出如何使用最新的C 11标准库来实现这一点,因为我需要使用统一的int分布或统一的real分布。我想我可以专门化模板: 在Visual Studio 2012 Update 3下,这给出了: 错误C2668:“‘匿名命名空间’::randomPrim

  • 在C 11中,如何专门化一个函数模板,该模板使用decltype声明为“复杂”的尾部返回类型?以下内容适用于GCC,但在VC2013中产生了“错误C2912:显式专业化‘int f(void)’i不是功能模板的专业化”: 我说“复杂”是因为缺乏一个技术上精确的词,因为我不确定是什么造成了差异。例如,以下decltype使用不依赖于任何函数结果类型的内置操作,可以与模板专业化配合使用: 自动f()-

  • 我试图调用一个模板类成员函数专门化,它从类的构造函数中返回一个值,但我似乎找不到正确的语法(如果存在的话)。下面是我的代码,下面是来自编译器(而不是链接器)的错误消息。 错误消息:g++-std=c++11-o t1 t1.cpp t1.cpp:19:18:错误:在'constexpr'模板constexpr const char*name()之前需要'<';^T1.CPP:22:26:错误:“c

  • 来自GHC 7.6的文档: [Y]你通常甚至不需要一开始的专业语用。当编译一个模块M时,GHC的优化器(with-o)会自动考虑在M中声明的每个顶级重载函数,并针对在M中调用它的不同类型对其进行专门化。优化器还会考虑每个导入的内联重载函数,并针对在M中调用它的不同类型对其进行专门化。 和 foo.hs: GHC专门用于调用,但在实例中不专门用于调用,这会降低性能。 但是,一个显式的杂注