Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 模板函子到特定函子的显式转换_C++_Templates_Functor_Crtp_Callable Object - Fatal编程技术网

C++ 模板函子到特定函子的显式转换

C++ 模板函子到特定函子的显式转换,c++,templates,functor,crtp,callable-object,C++,Templates,Functor,Crtp,Callable Object,我有一个可调用的structFoo定义为 struct Foo { template <typename T> void operator()(T i) const { /* ... */ } }; 基本上,foo.To()。 一种方法是使用lambdas: struct Foo { template <typename T> void operator()(T i) const { /* ... */ } template &

我有一个可调用的struct
Foo
定义为

struct Foo {
    template <typename T>
    void operator()(T i) const { /* ... */ }
};
基本上,
foo.To()。
一种方法是使用lambdas:

struct Foo {
    template <typename T>
    void operator()(T i) const { /* ... */ }

    template <typename T>
    auto To() const {
        return [this](T i) -> void {
            return this->operator()<T>(i);
        };
    }
};
structfoo{
样板
void运算符()(ti)常量{/*…*/}
样板
自动到()常量{
返回[this](ti)->void{
返回此->运算符()(i);
};
}
};

然而,我并不真正喜欢这个解决方案,因为它创建一个lambda并按值返回它,而我更喜欢对
Foo
进行某种“静态转换”,与对成员函数的简单调用相比,它没有计算开销。也可以采用CRTP解决方案,但它可能会为我希望更简单的事情添加太多样板代码实现上述目标最有效的方法是什么?

您认为会涉及额外的开销的假设不一定正确。编译器真的很擅长优化东西,在花时间重构代码之前,确认是否是这样总是值得的,因为这样做毫无益处

例如:

struct Foo {
    template <typename T>
    void operator()(T i) const;

    template <typename T>
    auto To() const {
        return [this](T i) -> void {
            return (*this)(i);
        };
    }
};

// Directly
void foo(const Foo& obj, char v) {
    return obj(v);
}

auto bar(const Foo& obj, int v) {
    return obj.To<char>()(v);
}

// As functors
auto get_foo_functor(const Foo& obj) {
  return obj;
}

auto get_To_functor(const Foo& obj) {
  return obj.To<char>();
}
structfoo{
样板
void运算符()(ti)常量;
样板
自动到()常量{
返回[this](ti)->void{
申报表(*本)(i);
};
}
};
//直接地
无效foo(const foo&obj,char v){
返回obj(v);
}
自动栏(常量Foo&obj,int v){
将对象返回到()(v);
}
//作为函子
自动获取函数(const-foo&obj){
返回obj;
}
自动获取到函子(常量Foo&obj){
返回obj.To();
}
Gcc将其编译为

foo(Foo const&, char):
        movsx   esi, sil
        jmp     void Foo::operator()<char>(char) const
bar(Foo const&, int):
        movsx   esi, sil
        jmp     void Foo::operator()<char>(char) const
get_foo_functor(Foo const&):
        xor     eax, eax
        ret
get_To_functor(Foo const&):
        mov     rax, rdi
        ret
foo(foo const&,char):
movsx esi,sil
jmp void Foo::operator()(char)const
条形图(Foo const&,int):
movsx esi,sil
jmp void Foo::operator()(char)const
get_foo_函子(foo const&):
异或eax,eax
ret
获取到函子(Foo const&):
莫夫拉克斯,rdi
ret

您可以在这里使用godbolt上的实时示例:

您是如何确定存在计算开销的?我很有信心,任何非脑残的编译器都会对它进行优化工作。编译器将为您进行此优化,无需麻烦。另外,为什么不简单地执行
foo.to(0)并完全跳过lambda?您是否计划存储lambda并在实际代码中调用之前传递它?@Frank@super您是否声称lambda解决方案将与普通函数调用一样高效?lambda解决方案是否至少还有一层间接层?我应该存储lambda并通过
const
引用返回它吗?因此,lambda解决方案基本上没有额外的性能成本,对吗?如果是这样的话,那么您就解决了我的疑问,非常感谢!只要您的编译器有一半的智能,并且您没有忘记启用优化,那么您就可以确信不会有任何开销。这里没有保证,但在性能方面也没有保证。
struct Foo {
    template <typename T>
    void operator()(T i) const;

    template <typename T>
    auto To() const {
        return [this](T i) -> void {
            return (*this)(i);
        };
    }
};

// Directly
void foo(const Foo& obj, char v) {
    return obj(v);
}

auto bar(const Foo& obj, int v) {
    return obj.To<char>()(v);
}

// As functors
auto get_foo_functor(const Foo& obj) {
  return obj;
}

auto get_To_functor(const Foo& obj) {
  return obj.To<char>();
}
foo(Foo const&, char):
        movsx   esi, sil
        jmp     void Foo::operator()<char>(char) const
bar(Foo const&, int):
        movsx   esi, sil
        jmp     void Foo::operator()<char>(char) const
get_foo_functor(Foo const&):
        xor     eax, eax
        ret
get_To_functor(Foo const&):
        mov     rax, rdi
        ret