SFINAE代码块

时间:2017-01-12 04:40:09

标签: c++ scope sfinae

在下面的代码中,当定义了SHOW_SFINAE_ON_TEMPLATED_ROUTINES_WORKS_AS_EXPECTED时,我们成功演示了SFINAE的方法实例。

但是,当定义了TRY_SFINAE_ON_CODE_BLOCK时,代码块上的替换失败,同时编译模板为" struct no_am" - 和编译错误。但是,编译器在编译时知道当模板是" struct no_am"时,不会执行这段代码。所以这次失败不应该是一个错误(或者我认为!)。

请解释为什么编译器可以在例程中应用SFINAE但无法在代码块上应用SFINAE。另外,如果有办法让编译器在代码块上应用SFINAE,请告诉我具体如何。

// 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;
}

0 个答案:

没有答案