std::enable_if to conditionally compile a member function(std::enable_if 有条件地编译成员函数)
问题描述
我试图通过一个简单的例子来理解如何使用 std::enable_if
.在我阅读了这个答案后,我认为应该不会太难举一个简单的例子.我想使用 std::enable_if
在两个成员函数之间进行选择,并且只允许使用其中一个.
I am trying to get a simple example to work to understand how to use std::enable_if
. After I read this answer, I thought it shouldn't be too hard to come up with a simple example. I want to use std::enable_if
to choose between two member-functions and allow only one of them to be used.
不幸的是,以下内容不能用 gcc 4.7 编译,经过数小时和数小时的尝试,我问你们我的错误是什么.
Unfortunately, the following doesn't compile with gcc 4.7 and after hours and hours of trying I am asking you guys what my mistake is.
#include <utility>
#include <iostream>
template< class T >
class Y {
public:
template < typename = typename std::enable_if< true >::type >
T foo() {
return 10;
}
template < typename = typename std::enable_if< false >::type >
T foo() {
return 10;
}
};
int main() {
Y< double > y;
std::cout << y.foo() << std::endl;
}
gcc 报告以下问题:
gcc reports the following problems:
% LANG=C make CXXFLAGS="-std=c++0x" enable_if
g++ -std=c++0x enable_if.cpp -o enable_if
enable_if.cpp:12:65: error: `type' in `struct std::enable_if<false>' does not name a type
enable_if.cpp:13:15: error: `template<class T> template<class> T Y::foo()' cannot be overloaded
enable_if.cpp:9:15: error: with `template<class T> template<class> T Y::foo()'
为什么g++不删除第二个成员函数的错误实例化?根据标准,std::enable_if
Why doesn't g++ delete the wrong instantiation for the second member function? According to the standard, std::enable_if< bool, T = void >::type
only exists when the boolean template parameter is true. But why doesn't g++ consider this as SFINAE? I think that the overloading error message comes from the problem that g++ doesn't delete the second member function and believes that this should be an overload.
推荐答案
SFINAE 仅在模板参数的参数推导中的替换使构造格式错误时才有效.没有这样的替代.
SFINAE only works if substitution in argument deduction of a template argument makes the construct ill-formed. There is no such substitution.
我也想到了这一点,并尝试使用 std::is_same<T, int >::value
和 !std::is_same
I thought of that too and tried to use
std::is_same< T, int >::value
and! std::is_same< T, int >::value
which gives the same result.
这是因为当类模板被实例化时(当你创建一个 Y
类型的对象时会发生这种情况),它会实例化它的所有成员声明(不一定是它们的定义/主体!).其中还有它的成员模板.请注意,T
是已知的,并且 !std::is_same<;T, int >::value
产生错误.所以它会创建一个类 Y
,其中包含
That's because when the class template is instantiated (which happens when you create an object of type Y<int>
among other cases), it instantiates all its member declarations (not necessarily their definitions/bodies!). Among them are also its member templates. Note that T
is known then, and !std::is_same< T, int >::value
yields false. So it will create a class Y<int>
which contains
class Y<int> {
public:
/* instantiated from
template < typename = typename std::enable_if<
std::is_same< T, int >::value >::type >
T foo() {
return 10;
}
*/
template < typename = typename std::enable_if< true >::type >
int foo();
/* instantiated from
template < typename = typename std::enable_if<
! std::is_same< T, int >::value >::type >
T foo() {
return 10;
}
*/
template < typename = typename std::enable_if< false >::type >
int foo();
};
std::enable_if
访问不存在的类型,因此该声明格式错误.因此您的程序无效.
The std::enable_if<false>::type
accesses a non-existing type, so that declaration is ill-formed. And thus your program is invalid.
您需要使成员模板的 enable_if
依赖于成员模板本身的参数.然后声明是有效的,因为整个类型仍然是依赖的.当您尝试调用其中之一时,会对其模板参数进行参数推导,并且 SFINAE 会按预期进行.见 这个问题以及有关如何做到这一点的相应答案.
You need to make the member templates' enable_if
depend on a parameter of the member template itself. Then the declarations are valid, because the whole type is still dependent. When you try to call one of them, argument deduction for their template arguments happen and SFINAE happens as expected. See this question and the corresponding answer on how to do that.
这篇关于std::enable_if 有条件地编译成员函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:std::enable_if 有条件地编译成员函数
基础教程推荐
- 调用std::Package_TASK::Get_Future()时可能出现争用情况 2022-12-17
- 什么是T&&(双与号)在 C++11 中是什么意思? 2022-11-04
- C++ 标准:取消引用 NULL 指针以获取引用? 2021-01-01
- 运算符重载的基本规则和习语是什么? 2022-10-31
- C++,'if' 表达式中的变量声明 2021-01-01
- 如何在 C++ 中处理或避免堆栈溢出 2022-01-01
- 设计字符串本地化的最佳方法 2022-01-01
- C++ 程序在执行 std::string 分配时总是崩溃 2022-01-01
- 您如何将 CreateThread 用于属于类成员的函数? 2021-01-01
- 如何定义双括号/双迭代器运算符,类似于向量的向量? 2022-01-01