草庐IT

c# - C++ 是否支持单个泛型方法而不是泛型类?

coder 2024-01-30 原文

Important: This question is getting quite long, if this is the first time you're reading this I suggest you start near the bottom as the solution is there in a round about way, but the code is a bit smelly.

看完tutorial on templates ,我能够更改我现有的类以支持泛型类型。但是,许多对象已经依赖于此,因此我正在寻找一种使方法通用而不是整个类的方法。

我尝试了以下方法,但似乎不支持这种行为。

// foobar1.h
// Don't want the entire class to be generic.
//template<class T>
class FooBar1
{
public:
    template<class T> T Foo();
}

// foobar2.h
class FooBar2 : public FooBar1
{
}

// foobar1.cpp
template<class T>
T FooBar1::Foo()
{
    return something;
}

// test.cpp
FooBar1 fb1;
FooBar2 fb2 = fb1.Foo<FooBar2>();

这应该不起作用,还是其他地方的错误让我感到困惑?

undefined reference to FooBar2 Foo<FooBar2>()

为了从某种角度说明我想要实现的目标,以下是我在 C# 中的实现方式 ...

public class FooBar1
{
    public T Foo<T>()
        where T : FooBar1
    {
        return something;
    }
}

public class FooBar2 : FooBar1 { }

FooBar1 fb1 = new FooBar1();
FooBar2 fb2 = fb1.Foo<FooBar2>();

有什么方法可以做类似于 C++ 的事情吗?

更新 1:

只是更正了一些小的语法细节(我的意思是公开 Foo,并返回 T,而不是 FooBar2)。仍然出现编译器错误......当我删除模板行为时,错误消失了,到目前为止的答案说我正在做的是有效的......但如果是这样,那为什么我仍然收到错误?感谢您的回答!

更新 2:

Josh,这是实际的源代码(好吧,我认为相关的部分,无论如何 - 如果您认为我跳过了重要的一点,请告诉我)。

// ImageMatrix.h
class ImageMatrix : public VImage
{
public:
    // ... various functions ...
    template<class T> T GetRotatedCopy(VDouble angle);
}

// ImageFilter.h
class ImageFilter : public ImageMatrix
{
    // ... various functions ...
}

// ImageMatrix.cpp
template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
    // ... create a new instance of ImageMatrix and return it.
}

// ImageProcessor.cpp
ImageFilter filter2 = filterPrototype.GetRotatedCopy<ImageFilter>(90);

这是实际的编译器错误:

/home/nick/Projects/ViMRID/vimrid/Debug/libvimrid.so: undefined reference to `vimrid::imaging::processing::ImageFilter vimrid::imaging::ImageMatrix::GetRotatedCopy(double)'

更新 3:

顺便说一句,除了实现行之外的所有内容都位于库中;所以它是从一个单独的二进制文件中调用的...这有关系吗? 更正;它都在同一个库中。不过,所有 block 都是不同的文件。

更新 4:

当我注释掉实现行 (ImageFilter filter2 = filterPrototype...) 时,它构建良好,所以似乎是这一行导致了它...

更新 5(已解决?):

仍有问题...这可能是命名空间的问题吗? 从头开始​​,好的,我现在已经掌握了模板的概念! :) 模板定义必须与声明一起位于标题中(对吗?)- 现在我已将声明移至 ImageMatrix.h ,一切编译。但是,我不得不使用 dynamic_cast让它工作;这是正确的吗?如果我跑题了请纠正我!

// This is in the header file!
// Help!!! This looks really really smelly...
template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
    ImageMatrix image = _getRotatedCopy(angle);
    ImageMatrix *imagePtr = &image;
    return *dynamic_cast<T*>(imagePtr);
}

更新 6:

引用更新 5,当我不使用 dynamic_cast 时......

template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
    ImageMatrix image = _getRotatedCopy(angle);
    ImageMatrix *imagePtr = &image;
    //return *dynamic_cast<T*>(imagePtr);
    return *imagePtr;
}

...我收到此错误...

../src/imaging/processing/../ImageMatrix.h: In member function ‘T vimrid::imaging::ImageMatrix::GetRotatedCopy(vimrid::VDouble) [with T = vimrid::imaging::processing::ImageFilter]’:
../src/imaging/processing/ImageProcessor.cpp:32:   instantiated from here
../src/imaging/processing/../ImageMatrix.h:45: error: conversion from ‘vimrid::imaging::ImageMatrix’ to non-scalar type ‘vimrid::imaging::processing::ImageFilter’ requested
make: *** [src/imaging/processing/ImageProcessor.o] Error 1

更新 7:

此外,如果我不在更新 6 中使用所有那些臭臭的代码...

class ImageMatrix : public VImage
{
public:
    template<class T> T GetRotatedCopy(VDouble angle);
private:
    ImageMatrix _getRotatedCopy(VDouble angle);
};

template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
    return _getRotatedCopy(angle);
}

...我收到与更新 6 中相同的错误。

最佳答案

是的,你非常接近,试试这个:

class FooBar1
{
public:
    template<class T> T Foo();
};

class FooBar2 : public FooBar1
{
};

template<class T>
T FooBar1::Foo()
{
    return T();
}

int main()
{
   FooBar1 fb1;
   FooBar2 fb2 = fb1.Foo<FooBar2>();
}

您遇到的问题是您指定了 FooBar1::Foo() 的返回类型作为FooBar2 , 你应该把它当作 T .

如果你想为 FooBar2 做特定的事情,你可以在 FooBar2 上特化:

template<>
FooBar2 FooBar1::Foo<FooBar2>()
{
    return FooBar2();
}

编辑: 听起来您遇到的问题是编译器找不到模板化 GetRotatedCopy 的定义。 C++ 中的模板相当挑剔,通常的做法是将整个模板实现放在一个头文件中。你可以试试这个:

class ImageMatrix : public VImage
{
public:
    // ... various functions ...
    template<class T> T GetRotatedCopy(VDouble angle)
    {
       // ... create a new instance of ImageMatrix and return it.
    }
};

编辑: 我找不到 gcc 文档,但这里是 microsoft's documentation在显式模板实例化和库上,它提供了一些关于正在发生的事情的想法。您可能希望按照我之前的建议在 header 中包含实现,或者在库中调用 GetRotatedCopy,或者在库中显式实例化它。参见 veefu's answer下面是语法。

之所以与 C# 不同,是因为 C++ 中的模板与 C# 不同,实际上为每个不同的模板参数组合创建了一个全新的类/函数。例如vector<int>是与 vector<string> 完全不同的类(具有不同的编译方法集) .参见 Kevin's answer以获得更好的解释。

至于当你不使用模板时错误消失,这实际上并没有告诉你太多,因为直到你真正实例化一个模板,它不会

RE 更新 5、6、7

你的 dynamic_cast 不会工作,你只能在指针实际指向你正在转换的类的实例时使用它。 (它的工作方式类似于 C# 中的 as 运算符)。

我现在怀疑,您想要的是 CRTP .您从 ImageFilter 的实例开始,并希望在其上使用基类方法,并取回 ImageFilter 的新拷贝。尝试以下方法:

template <class T>
class ImageMatrix
{
public:
    T GetRotatedMatrix()
    {
        return T();
    }
};

class ImageFilter : public ImageMatrix<ImageFilter>
{
};

int main()
{
    ImageFilter filterPrototype;
    ImageFilter otherFilter = filterPrototype.GetRotatedMatrix();
}

否则,如果您真的想从 ImageMatrix 开始并将其转换为 ImageFilter,则必须在采用 ImageMatrix 的 ImageFilter 上添加一个构造函数。

关于c# - C++ 是否支持单个泛型方法而不是泛型类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/735184/

有关c# - C++ 是否支持单个泛型方法而不是泛型类?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  5. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  6. Ruby 方法() 方法 - 2

    我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby​​-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco

  7. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  8. ruby - Highline 询问方法不会使用同一行 - 2

    设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

  9. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  10. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

随机推荐