我的程序生成具有“类型”和标识符的随机字符串。像这样:
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
无所事事,而不是生成编译错误?
答案 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) ); }
如果您不想使用宏(这是可以理解的)。