【问题标题】:Can static class functions of a templated class be used without a template parameter?模板类的静态类函数可以在没有模板参数的情况下使用吗?
【发布时间】:2012-05-16 18:27:15
【问题描述】:

我有一个模板类,其中包含一个不依赖于模板参数的静态函数。然而,当我使用该函数时,编译器似乎强制我指定一个类型名。

template <typename T>
class MyClass {
    ...
    static void function();
};

template <typename T>
void MyClass<T>::function() {
    ....
}

这个函数可以用作:

MyClass<int>::function();

但“int”只是为了满足编译器的需要。它没有任何意义,可以替换为任何其他类型,这不会增加代码的可读性。我想做一些类似的事情

MyClass<>::function();

甚至

MyClass::function();

但编译器不允许我这样做。我意识到这是因为在头文件中我已将函数明确标记为模板化,但是当我从头文件中删除“”时,它也无法编译。

这样做的正确方法是什么?

【问题讨论】:

  • 如果模板被实例化的类型不影响函数,我想知道它是否真的应该是一个成员函数(甚至是静态的)。也许它真的应该是同一个命名空间中的外部函数? (不要误解:我并不是说当前的设计错的,只是我会三思而后行)。
  • @Jerry - 我想不出这种设计不会出错的情况。也许在外部不是正确的反应,它可能在一个基础上,但显然在不需要它的地方使用模板系统是不好的。你能想出什么理由可以保证这样做吗?
  • 您绝对应该考虑将其设为非成员函数。如果您不相信,请查看 Scott Meyers 的这篇文章,“How Non-Member Functions Improve Encapsulation”。
  • @CrazyEddie:不,我想不出理由——我只是犹豫要直接谴责它,而不知道发生了什么。
  • 如果它与 T 无关,因此与 MyClass 无关,并且不接受与 T 相关的参数,那么它似乎不应该是类的成员。也许一个独立的功能更合适。

标签: c++ templates


【解决方案1】:

类型很重要!

模板可以专门化,因此:

template <typename T>
class MyClass {
public:
    static void function() { std::cout << "Hello, World!\n"; }
};


template <>
class MyClass<City> {
public:
    static void function() { launchRockets(); }
};

是一个可行的计划。

如果你然后写MyClass::function(),它应该歼灭巴格达还是打印一个友好的消息?


当然,如果这个函数没有理由做打印以外的任何事情,那么它也许应该是一个独立的函数

void function() { std::cout << "Hello, World!\n"; }

function()简单调用,嘿嘿,没有类就更短了!

【讨论】:

  • 我认为最重要的是,MyClass::function() 没有意义,因为MyClass 不是一个实际的类。
  • @LuchianGrigore:我同意,但是我选择了另一种攻击角度来试图让 OP 理解为什么它是无意义的,而不是仅仅断言它。
  • 这是一个很好的论据。 +1。但我认为应该尽早解决类和模板类之间的混淆。
  • 我想将function() 放在MyClass 中的唯一原因是它在概念上 与MyClass 相关。在您的示例中, function() 所做的事情应该取决于类型名。
  • @marcelnijman:这就是命名空间的用途:将相关的类和函数组合在一起。如果关系这么密切,那就在同一个header中声明一下,说明清楚。如果只是相关,则将两个标题放在同一个文件夹中,并且都位于同一个命名空间中。
【解决方案2】:

想象一下你有这个:

template <typename T> struct Foo
{
    static void boom()
    {
        static int n = 0;
        std::cout << ++n << std::endl;
    }
};

现在想象一下,如果你说 Foo&lt;int&gt;::boom(); Foo&lt;int&gt;::boom(); 会发生什么,并将其与根本不等同的 Foo&lt;int&gt;::boom(); Foo&lt;char&gt;::boom(); 进行比较。

【讨论】:

  • 我认为这最能回答我的问题。所以,基本上,我可以选择添加一个无意义的类型(让我的代码的读者感到困惑)或通过将函数放置在无上下文的全局函数池中来从类中删除函数。或者是否有其他选项可以明确 function() 在概念上 属于 MyClass?
  • @marcelnijman:我认为公共命名空间是最干净的解决方案。
【解决方案3】:

不要将template 视为class。它只是构建类的骨架。

MyClass::function() 没有任何意义,因为MyClass 不是一个实际的类,除非你对其进行专门化。

MyClass&lt;int&gt;::function();MyClass&lt;char&gt;::function(); 可能不依赖于模板参数,它们的行为可能相同,但它们的功能不同。

让我们看一下二进制文件:

    MyClass<int>::function();
00D617CE  call        MyClass<int>::function (0D611C2h) 
    MyClass<char>::function();
00D617D3  call        MyClass<char>::function (0D611C7h) 

为此,我为function 提供了一个空定义,因此它绝对不依赖于模板参数。如您所见,这两个功能是不同的。

这是因为编译器生成了两个类 - MyClass&lt;int&gt;MyClass&lt;char&gt;

【讨论】:

  • 是否可以指定一个独立于类型名但又添加到每个专业化的函数定义?
猜你喜欢
  • 1970-01-01
  • 2021-08-30
  • 2011-04-11
  • 2012-10-11
  • 1970-01-01
  • 2012-05-03
  • 1970-01-01
  • 1970-01-01
  • 2018-02-28
相关资源
最近更新 更多