C++ 码块上的SFINAE
在下面的代码中,当定义了SHOW_SFINAE_ON_TEMPLATED_ROUTINES_WORKS_AS_EXPECTED时,我们成功地演示了SFINAE ON methods的一个实例 但是,当定义了“代码”块上的TRY\u SFINAE\u时,在编译模板为“struct no\u am”时,代码块上的替换失败,编译错误将消失。然而,编译器在编译时知道,当模板为“struct no__am”时,不会执行这段代码,所以这个失败不应该是一个错误(或者我认为是这样!) 请解释为什么编译器可以在例程上应用SFINAE,但不能在代码块上应用SFINAE。另外,如果有一种方法可以让编译器在代码块上应用SFINAE,请告诉我具体的方法C++ 码块上的SFINAE,c++,scope,sfinae,C++,Scope,Sfinae,在下面的代码中,当定义了SHOW_SFINAE_ON_TEMPLATED_ROUTINES_WORKS_AS_EXPECTED时,我们成功地演示了SFINAE ON methods的一个实例 但是,当定义了“代码”块上的TRY\u SFINAE\u时,在编译模板为“struct no\u am”时,代码块上的替换失败,编译错误将消失。然而,编译器在编译时知道,当模板为“struct no__am”时,不会执行这段代码,所以这个失败不应该是一个错误(或者我认为是这样!) 请解释为什么编译器可以在例
// Compiled via command:
// x86_64_6.2.0_posix_seh_rt_v5_rev1/mingw64/bin/x86_64-w64-mingw32-g++.exe -D_WIN64 -Wall -Wextra -Werror -std=c++11 -O3 -static-libgcc -static-libstdc++ sfinae_on_code_block.cc -o sfinae.exe
#define SHOW_SFINAE_ON_TEMPLATED_ROUTINES_WORKS_AS_EXPECTED
//#define TRY_SFINAE_ON_CODE_BLOCK
#include <fstream>
#include <iostream>
#include <thread>
#include <mutex>
template< typename T >
struct a_member_trait{
static const bool exists = false;
static const bool is_float = false;
};
template< class T >
class see_sfinae_member_traits
{
public:
see_sfinae_member_traits( T t ) : the_t(t)
{
}
T the_t;
#ifdef SHOW_SFINAE_ON_TEMPLATED_ROUTINES_WORKS_AS_EXPECTED
void speak( const std::string& msg )
{
std::cout << msg << ": ";
speak_sfinae<T>();
}
template< class X >
typename std::enable_if< a_member_trait<X>::exists == true &&
a_member_trait<X>::is_float == true >::type
speak_sfinae()
{
std::cout << "Has a_member, and that a_member is a float ["
<< the_t.a_member
<< "]"
<< std::endl;
}
template< class X >
typename std::enable_if< a_member_trait<X>::exists == true &&
a_member_trait<X>::is_float == false >::type
speak_sfinae()
{
std::cout << "Has a_member, and that a_member is NOT a float ["
<< the_t.a_member
<< "]"
<< std::endl;
}
template< class X >
typename std::enable_if< a_member_trait<X>::exists == false &&
a_member_trait<X>::is_float == false >::type
speak_sfinae()
{
std::cout << "Does NOT have a_member, float or otherwise"
<< std::endl;
}
#endif
#ifdef TRY_SFINAE_ON_CODE_BLOCK
void tell( const std::string& msg )
{
std::cout << msg << ": ";
tell_all<T>();
}
template< class X >
void tell_all()
{
std::cout << "from tell all: ";
if( a_member_trait<X>::exists == true && a_member_trait<X>::is_float == true )
{
std::cout << "Has a_member, and that a_member is a float ["
<< the_t.a_member
<< "]"
<< std::endl;
}
if( a_member_trait<X>::exists == true && a_member_trait<X>::is_float == false )
{
std::cout << "Has a_member, and that a_member is NOT a float"
<< the_t.a_member
<< "]"
<< std::endl;
}
if( a_member_trait<X>::exists == false && a_member_trait<X>::is_float == false )
{
std::cout << "Does NOT have a_member, float or otherwise"
<< std::endl;
}
}
#endif
};
struct has_fam
{
float a_member{ 1.1f };
};
struct has_iam
{
int a_member{ 1 };
};
struct no_am
{
int b_member{ 2 };
};
template<>
struct a_member_trait< has_fam >{
static const bool exists = true;
static const bool is_float = true;
};
template<>
struct a_member_trait< has_iam >{
static const bool exists = true;
static const bool is_float = false;
};
int main()
{
has_fam x_fam;
has_iam x_iam;
no_am x_noam;
see_sfinae_member_traits< has_fam > ht_fam( x_fam );
see_sfinae_member_traits< has_iam > ht_iam( x_iam );
see_sfinae_member_traits< no_am > ht_noam( x_noam );
#ifdef SHOW_SFINAE_ON_TEMPLATED_ROUTINES_WORKS_AS_EXPECTED
ht_fam.speak( "hast_fam" );
ht_iam.speak( "hast_iam" );
ht_noam.speak( "not_am" );
#endif
#ifdef TRY_SFINAE_ON_CODE_BLOCK
ht_fam.tell( "hast_fam" );
ht_iam.tell( "hast_iam" );
ht_noam.tell( "not_am" );
#endif
return 0;
}
//通过命令编译:
//x86_64_6.2.0_posix_seh_rt_v5_rev1/mingw64/bin/x86_64-w64-mingw32-g++.exe-D_WIN64-Wall-Wextra-Werror-std=c++11-O3-静态libgcc-static libstdc++sfinae_on_code\u block.cc-o sfinae.exe
#按预期在模板化的例程上定义SHOW\u SFINAE\u
//#在代码块上定义TRY\u SFINAE\u
#包括
#包括
#包括
#包括
模板
构造一个成员特征{
静态常量bool exists=false;
静态常量bool为\u float=false;
};
模板
类请参见成员特征
{
公众:
参见成员特征(T):成员特征(T)
{
}
(三);
#ifdef在模板化例程上显示SFINAE,并按预期工作
void speak(const std::string和msg)
{
std::cout::type
说
{
std::我可以想象在其中起作用的一个原因是,如果代码块工作正常,您将无法获得代码的完整调试版本
,基本上删除死代码,非优化版本会用它做什么?它当然会为块创建代码。基本上这里有死代码,它与SFINAE无关:if(false){…}
。这是什么“代码块上的SFINAE”你说的是哪一个?没有这样的东西。块中的代码必须是格式良好的,即使它没有执行。至少在你身边有一个优秀的编译器之前。希望接受@IgorTandetnik的注释作为答案(cf.)