使用SFINAE但不会产生编译错误

时间:2013-11-25 19:09:20

标签: c++ c++11 sfinae

我的程序生成具有“类型”和标识符的随机字符串。像这样:

float       lHTY8Au8b9 = float();
int         dO3PNUInH6 = int();
float       B_MtShimak = float();
float       hgi_TzaVEv = float();
double      mfW8kr6h6q = double();
std::string lSLj9antfj = std::string();
char        MQkeARWYTL = char();
char        Oe7G_ZRJy6 = char();
float       qUwmOWeilK = float();
double      FJYIODwQfx = double();

然后我有以下内容来查看是否可以添加两个任意变量:

template <typename A, typename B>
typename std::enable_if<std::is_convertible<A, B>::value, decltype(A() + B())>::type
    try_to_add(A a, B b) {
        return a + b;
    }

当然,它有效,因为我收到以下错误:

main.cpp:51:54: error: no matching function for call to ‘try_to_add(double&, std::string&)’

  try_to_add<double,std::string>(mfW8kr6h6q,lSLj9antfj);

然而,我想要的是一个不会导致编译错误的候选列表。我无法对模板参数进行硬编码,因为它只接受整数,我无法检查生成器程序内部,因为它们只是字符串,并且尝试将try_to_add与不可转换类型一起使用将导致编译错误。我知道SFINAE是错误的方法,但是有没有办法让try_to_add无所事事,而不是生成编译错误?

Coliru

2 个答案:

答案 0 :(得分:4)

使用不执行任何操作的反向条件添加另一个重载。

template <typename A, typename B>
typename std::enable_if<!std::is_convertible<A, B>::value>::type
try_to_add(A, B) { }

答案 1 :(得分:3)

这是一些有用的技巧。首先,我们只是尝试添加,而不是is_convertible。如果它有效,奖金。其次,我使用完美转发。

最后,我使用一个variardic包来“完成工作”。这是sink技术。

#include <iostream>

#define RETURNS(X) ->decltype(X) { return (X); }

template<typename A, typename B>
auto try_to_add(A&& a, B&& b)
  RETURNS( std::forward<A>(a) + std::forward<B>(b) )

template<typename... Ts>
void try_to_add( Ts&&... ) {
  std::cout  << "failed to add\n";
}

struct foo {};

int main() {
  int a =1, b=2;
  std::cout << try_to_add( a, b ) << "\n";
  try_to_add( a, foo{} );
}

RETURNS宏解决了C ++ 11中缺少自动返回类型推导的问题。在C ++ 1y中,我们将有一个更好的选项,让我们省略重复的-> (X) { returns (X); }烦恼。

变量arigard的意思是,如果没有variardic args的所有重载都不匹配(它们被认为是最后一个),这样的包只会匹配。这很有用,因为您不必一次将bool条件保持在两个不同的位置(一旦倒置)。

可以扩展RETURNS宏:

template<typename A, typename B>
auto try_to_add(A&& a, B&& b)
-> decltype( std::forward<A>(a) + std::forward<B>(b) )
  { return ( std::forward<A>(a) + std::forward<B>(b) ); }

如果您不想使用宏(这是可以理解的)。