C++ 如何转发对成员函数模板的调用,该模板可以是常量,也可以是非常量,具体取决于模板类型?
我有一些类似的东西(将示例简化到相关点) 很明显,C++ 如何转发对成员函数模板的调用,该模板可以是常量,也可以是非常量,具体取决于模板类型?,c++,c++14,template-meta-programming,C++,C++14,Template Meta Programming,我有一些类似的东西(将示例简化到相关点) 很明显,Bar::constFn不会编译,因为它调用非常量函数Foo::Nested::get——即使TypeA满足someTrait并最终再次调用const函数constepr Foo::get()const 暂时不考虑constexpr,如何在嵌套类的函数模板中传播被调用函数的constess?我试着简单地用一个常量和非常量版本的Nested::get重载它,它解决了macOS上的叮当声,但在Windows上的Visual Studio 2015中使
Bar::constFn
不会编译,因为它调用非常量函数Foo::Nested::get
——即使TypeA
满足someTrait
并最终再次调用const函数constepr Foo::get()const
暂时不考虑constexpr,如何在嵌套类的函数模板中传播被调用函数的constess?我试着简单地用一个常量和非常量版本的Nested::get
重载它,它解决了macOS上的叮当声,但在Windows上的Visual Studio 2015中使用MSVC失败了,不幸的是,这是一个必需的构建目标
请注意,原始示例包含的不仅仅是两个版本的Foo::get
,因此我希望避免重复Foo::Nested
中的所有版本,但如果可能,可以使用一个或两个函数模板转发它
编辑:我尝试使用该提案
template <typename T>
constexpr auto get() const -> decltype(foo.get<T>()) { return foo.get<T>(); }
template <typename T>
constexpr auto get() -> decltype(foo.get<T>()) { return foo.get<T>(); }
模板
constexpr auto get()const->decltype(foo.get()){return foo.get();}
模板
constexpr auto get()->decltype(foo.get()){return foo.get();}
对于当前的MSVC版本,它似乎编译得很好,但在Visual Studio 2015 MSVC 19.0中失败,因此这是没有选项的。首先,您需要
启用\u if::type
,SFINAE才能工作
要回答您的问题,您需要重载Nested::get
:
#include <type_traits>
struct Foo
{
template <typename T>
constexpr std::enable_if_t<std::is_integral_v<T>, T>&
get() const
{ return something(); }
template <typename T>
std::enable_if_t<std::is_floating_point_v<T>, T>&
get()
{ return somethingDifferent(); }
int& something() const;
float& somethingDifferent();
class Nested
{
public:
Nested();
template <typename T>
constexpr std::enable_if_t<std::is_integral_v<T>, T>&
get() const { return foo.get<T>(); }
template <typename T>
std::enable_if_t<std::is_floating_point_v<T>, T>&
get() { return foo.get<T>(); }
private:
Foo& foo;
};
};
#包括
结构Foo
{
模板
constexpr std::启用&
get()常量
{返回某物();}
模板
std::如果启用,则启用&
得到()
{返回somethingthesist();}
int&something()常量;
浮动&somethingthesis();
类嵌套
{
公众:
嵌套();
模板
constexpr std::启用&
get()常量{return foo.get();}
模板
std::如果启用,则启用&
get(){return foo.get();}
私人:
富和富;
};
};
类栏:公共Foo::嵌套
{
void nonstfn()
{
[maybe_unused]]auto&a=get();
[maybe_unused]]auto&b=get();
}
void constFn()常量
{
[maybe_unused]]auto&a=get();
}
};
首先,您需要
启用\u if::type
,SFINAE才能工作
要回答您的问题,您需要重载Nested::get
:
#include <type_traits>
struct Foo
{
template <typename T>
constexpr std::enable_if_t<std::is_integral_v<T>, T>&
get() const
{ return something(); }
template <typename T>
std::enable_if_t<std::is_floating_point_v<T>, T>&
get()
{ return somethingDifferent(); }
int& something() const;
float& somethingDifferent();
class Nested
{
public:
Nested();
template <typename T>
constexpr std::enable_if_t<std::is_integral_v<T>, T>&
get() const { return foo.get<T>(); }
template <typename T>
std::enable_if_t<std::is_floating_point_v<T>, T>&
get() { return foo.get<T>(); }
private:
Foo& foo;
};
};
#包括
结构Foo
{
模板
constexpr std::启用&
get()常量
{返回某物();}
模板
std::如果启用,则启用&
得到()
{返回somethingthesist();}
int&something()常量;
浮动&somethingthesis();
类嵌套
{
公众:
嵌套();
模板
constexpr std::启用&
get()常量{return foo.get();}
模板
std::如果启用,则启用&
get(){return foo.get();}
私人:
富和富;
};
};
类栏:公共Foo::嵌套
{
void nonstfn()
{
[maybe_unused]]auto&a=get();
[maybe_unused]]auto&b=get();
}
void constFn()常量
{
[maybe_unused]]auto&a=get();
}
};
在嵌套的
中需要常量和非常量重载,可以避免用另一个(简单的)SFINAE重复所有重载/SFINAE:
类嵌套
{
Foo&Foo;//应在decltype用法之前声明
公众:
嵌套();
模板
constexpr auto get()const->(decltype(foo.get()){return foo.get();}
模板
constexpr auto get()->(decltype(foo.get()){return foo.get();}
};
在嵌套的中需要常量和非常量重载,可以避免用另一个(简单的)SFINAE重复所有重载/SFINAE:
类嵌套
{
Foo&Foo;//应在decltype用法之前声明
公众:
嵌套();
模板
constexpr auto get()const->(decltype(foo.get()){return foo.get();}
模板
constexpr auto get()->(decltype(foo.get()){return foo.get();}
};
考虑以下问题,这些问题毫无意义,但可以为您的问题提供解决方案。您有一个包含两个函数的类和它们的调用程序
class A
{
public: void foo() { printf("foo"); }
public: void foo() const { printf("foo const"); }
public: void invoke() { foo(); }
}
如果执行A().invoke()
,显然会得到foo
。如果您想强制执行const
type函数,您是如何实现的?好的,您进行以下更改
A::invoke(){const_cast(this)->foo();}
就是这样。考虑下面的问题,这个问题毫无意义,但可以为您的问题提供解决方案。您有一个包含两个函数的类和它们的调用程序
class A
{
public: void foo() { printf("foo"); }
public: void foo() const { printf("foo const"); }
public: void invoke() { foo(); }
}
如果执行A().invoke()
,显然会得到foo
。如果您想强制执行const
type函数,您是如何实现的?好的,您进行以下更改
A::invoke(){const_cast(this)->foo();}
就是这样。请始终添加语言标记您完成了大部分工作,只需将代码剥离到相关部分即可。您只需要创建一个实际的。我想回答您的问题,为此我需要测试我的解决方案,但我没有可以编译的代码。首先,我需要编译您的代码(Foo部分),这是您应该做的事情。如果不是在我们的时间,想想你没有得到的潜在答案,因为人们看到他们必须做你的工作来帮助你时,他们只是继续前进。请始终添加语言标记,通过将代码剥离到相关部分,你完成了大部分工作。您只需要创建一个实际的。我想回答您的问题,为此我需要测试我的解决方案,但我没有可以编译的代码。首先,我需要编译您的代码(Foo部分),这是您应该做的事情。如果不是因为我们的t
class Nested
{
Foo& foo; // Should be declared before the decltype usage
public:
Nested();
template <typename T>
constexpr auto get() const -> (decltype(foo.get<T>())) { return foo.get<T>(); }
template <typename T>
constexpr auto get() -> (decltype(foo.get<T>())) { return foo.get<T>(); }
};
class A
{
public: void foo() { printf("foo"); }
public: void foo() const { printf("foo const"); }
public: void invoke() { foo(); }
}