SO 上有几个问题解决了将函数指针作为参数/实参传递的问题(here、here、here 等)。其实我问了一个related question另一天。但是,这个问题有点不同。
我的问题是我正在编写一个非常灵活的类。
我现在拥有的适用于非成员函数。下面贴出来
template <typename T>
class MyClass
{
private:
typedef double (*firstFunctionPtr) (const T &var);
typedef bool (*secondFunctionPtr)(const T &var);
// Function pointers as member variables
firstFunctionPtr _firstFunc;
secondFunctionPtr _secondFunc;
public:
inline MyClass(firstFunctionPtr firstFunc,
secondFunctionPtr secondFunc);
};
template<typename T>
MyClass<T>::MyClass(firstFunctionPtr firstFunc, secondFunctionPtr secondFunc) :
_firstFunc(firstFunc),
_secondFunc(secondFunc),
{}
但是,当我需要使用指向某个其他任意类的成员函数的指针进行初始化时,这种方法就会崩溃,不幸的是,对于我来说,这恰好是我的目的的常见用例。
In a proper C++ interface you might want to have a look at having your function take templated argument for function objects to use arbitrary class types.
但是,我无法编译。我试过模板化我的 typedef(使用 C++11 别名方法),并且我试过向类添加第二个模板参数来处理那些成员函数的调用类,但是这两种方法都没有用。
This Q/A似乎正在朝着我想要做的事情发展,但我无法弄清楚它的正面或反面。
郑重声明,我试图避免使用 functional header ,但不使用它可能是愚蠢的差事。
最佳答案
如果你想要MyClass成为一个可以同时拥有自由功能的模板
类型指针:
double (*)(const T &var);
bool (*)(const T &var);
对于某些参数类型 T , 或者成员函数
类型指针:
double (C::*)(const T &var);
bool (C::*)(const T &var);
对于某些参数类型 C和 T然后,MyClass必须参数化
由两者T和 C并且您需要两个专业:
C是一些非类类型C是任何类类型在情况(1)中,非类类型 C不可能有成员函数,
以便实现自由函数指针特化。
在情况 (2) 中,类 C可以是一个有成员函数的,这样一个
将实现成员函数指针特化。
非类类型的明显选择 C是void .所以我们可以制作C
默认为 void :
主模板
template<typename T, typename C = void>
struct MyClass;
这样:
MyClass<T>
将是 T 的自由函数指针特化, 和:
MyClass<T,C>
对于任何C除了void , 将是成员函数指针特化。
如您所知,您可以使用 std::enable_if
和 SFINAE 使编译器
选择类模板的一种特化或另一种特化,取决于是否
它的模板参数 U满足一些编译时测试。你可以拿
这里的方法,但另一种不需要该设备的方法可用:
从主模板开始,我们只想拥有:
免费函数特化
template<typename T>
struct MyClass<T>
{
... for free function pointers ...
};
和:
成员函数特化
template<typename T, typename C>
struct MyClass<T,C>
{
... for member function pointers ...
};
但我们不能只拥有它,因为成员函数“specialization”恰好有 与主模板相同的模板参数。这意味着它不是 特化,编译器不允许。
但是,您可以轻松地解决这个问题,只需提供主要的 template 一个它不需要的默认模板参数,但是它的 存在使这两个专业都能站稳脚跟。
新主模板
template <typename T, typename C = void, typename Default = void>
struct MyClass;
所以这是一个说明性的解决方案:
// Primary template
template <typename T, typename C = void, typename Default = void>
struct MyClass;
// Free function specialization
template <typename T>
struct MyClass<T>
{
using firstFunctor_t = double(*)(T const &);
using secondFunctor_t = bool(*)(T const &);
MyClass(firstFunctor_t firstFunc, secondFunctor_t secondFunc)
: _firstFunc(firstFunc),
_secondFunc(secondFunc)
{}
double callFirst(T const & var) {
return _firstFunc(var);
}
bool callSecond(T const & var) {
return _secondFunc(var);
}
private:
firstFunctor_t _firstFunc;
secondFunctor_t _secondFunc;
};
// Member function specialization
template <typename T, typename C>
struct MyClass<T,C>
{
using firstFunctor_t = double(C::*)(T const &);
using secondFunctor_t = bool(C::*)(T const &) const;
MyClass(firstFunctor_t firstFunc, secondFunctor_t secondFunc)
: _firstFunc(firstFunc),
_secondFunc(secondFunc)
{}
double callFirst(C & obj, T const & var) {
return (obj.*_firstFunc)(var);
}
double callFirst(C const & obj, T const & var) {
auto & o = const_cast<C&>(obj);
return (o.*_firstFunc)(var);
}
bool callSecond(C & obj, T const & var) {
return (obj.*_secondFunc)(var);
}
bool callSecond(C const & obj, T const & var) {
auto & o = const_cast<C&>(obj);
return (o.*_secondFunc)(var);
}
private:
firstFunctor_t _firstFunc;
secondFunctor_t _secondFunc;
};
在成员函数特化中,注意两点你可能 没有考虑过:-
我决定要存储的第二个成员函数应该是
const 成员函数。 C 的成员函数很可能是
需要 T const &参数和返回 bool 将是 const成员
功能,不是吗?如果是这样,那么const-ness必须是的一部分
我在特化中使用的成员函数类型定义:
using secondFunctor_t = bool(C::*)(T const &) const;
或尝试用任何 bool (C::*)(T const &) const 实例化特化
将无法编译。
另外,我为每个 MyClass<T,C>::callFirst 提供了两个重载
和 MyClass<T,C>::callSecond , 一个带参数:
C & obj, T const & var
还有一个带参数的:
C const & obj, T const & var
没有第二个,尝试调用 MyClass<T,C>::callFirst
或 MyClass<T,C>::callSecond用obj那是 const 将失败
编译。
对于演示此解决方案的程序,您可以附加:
#include <iostream>
#include <string>
double foo(std::string const & s)
{
return std::stod(s);
}
bool bar(std::string const & s)
{
return s.size() > 0;
}
struct SomeClass
{
SomeClass(){};
double foo(std::string const & s) {
return ::foo(s);
}
bool bar(std::string const & s) const {
return ::bar(s);
}
};
int main()
{
MyClass<std::string> my0{foo,bar};
std::cout << std::boolalpha;
std::cout << my0.callFirst("1.11") << std::endl;
std::cout << my0.callSecond("Hello World") << std::endl;
MyClass<std::string,SomeClass> my1{&SomeClass::foo,&SomeClass::bar};
SomeClass thing;
std::cout << my1.callFirst(thing,"2.22") << std::endl;
std::cout << my1.callSecond(thing,"Hello World") << std::endl;
SomeClass const constThing;
std::cout << my1.callFirst(constThing,"3.33") << std::endl;
std::cout << my1.callSecond(constThing,"Hello World") << std::endl;
return 0;
}
您说您希望此模板“极其灵活”。这 图示解决方案适合您的示例,但您可能 有兴趣知道它几乎没有您所能得到的那么灵活。 对于自由函数和成员函数,附加 variadic template 参数,您的模板可以存储和调用 [member] 函数 任意返回类型和任意类型参数的任意数量。 参见 this question和 回答。
关于c++ - 将任意类的成员函数指针存储为类实例变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42182980/
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs