#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>
template<typename InIt, typename OutIt, typename Fun>
class is_valid_transform
{
private:
class YES
{
char dummy[2]; // size > 1
};
typedef char NO; // size == 1
// std::transform has return type OutIt which will only convert to
// InIt if OutIt does not have stronger const-ness properties.
static YES test(InIt);
// SFINAE fallback: ... has lowest priority
static NO test(...);
public:
// equivalent to sizeof(test(OutIt()) != sizeof(NO)
static const bool value = sizeof(test(std::transform(InIt(), InIt(), OutIt(), Fun()))) != sizeof(NO);
};
int main()
{
typedef std::vector<int>::iterator iter1;
typedef std::vector<int>::const_iterator iter2;
typedef std::vector<std::string>::iterator iter3;
typedef std::negate<int> func;
auto strinf = [](int)->std::string { return "hello"; };
std::cout << "valid transform compiles: " << is_valid_transform<iter1,iter1,func>::value << std::endl;
std::cout << "invalid transform compiles: " << is_valid_transform<iter1,iter2,func>::value << std::endl;
std::cout << "valid transform compiles: " << is_valid_transform<iter2,iter1,func>::value << std::endl;
std::cout << "invalid transform compiles: " << is_valid_transform<iter1,iter3,decltype(&strinf)>::value << std::endl;
std::transform(iter1(), iter1(), iter3(), strinf);
return 0;
}
I2luY2x1ZGUgPGFsZ29yaXRobT4KICAgICNpbmNsdWRlIDxmdW5jdGlvbmFsPgogICAgI2luY2x1ZGUgPGlvc3RyZWFtPgogICAgI2luY2x1ZGUgPHZlY3Rvcj4KCiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBJbkl0LCB0eXBlbmFtZSBPdXRJdCwgdHlwZW5hbWUgRnVuPgogICAgY2xhc3MgaXNfdmFsaWRfdHJhbnNmb3JtCiAgICB7CiAgICBwcml2YXRlOgogICAgICAgICAgICBjbGFzcyBZRVMKICAgICAgICAgICAgeyAKICAgICAgICAgICAgICAgICAgICBjaGFyIGR1bW15WzJdOyAvLyBzaXplID4gMQogICAgICAgICAgICB9OwoKICAgICAgICAgICAgdHlwZWRlZiBjaGFyIE5POyAvLyBzaXplID09IDEKCiAgICAgICAgICAgIC8vIHN0ZDo6dHJhbnNmb3JtIGhhcyByZXR1cm4gdHlwZSBPdXRJdCB3aGljaCB3aWxsIG9ubHkgY29udmVydCB0byAKICAgICAgICAgICAgLy8gSW5JdCBpZiBPdXRJdCBkb2VzIG5vdCBoYXZlIHN0cm9uZ2VyIGNvbnN0LW5lc3MgcHJvcGVydGllcy4KICAgICAgICAgICAgc3RhdGljIFlFUyB0ZXN0KEluSXQpOwoKICAgICAgICAgICAgLy8gU0ZJTkFFIGZhbGxiYWNrOiAuLi4gaGFzIGxvd2VzdCBwcmlvcml0eQogICAgICAgICAgICBzdGF0aWMgTk8gdGVzdCguLi4pOwoKICAgIHB1YmxpYzogCiAgICAgICAgICAgIC8vIGVxdWl2YWxlbnQgdG8gc2l6ZW9mKHRlc3QoT3V0SXQoKSkgIT0gc2l6ZW9mKE5PKSAKICAgICAgICAgICAgc3RhdGljIGNvbnN0IGJvb2wgdmFsdWUgPSBzaXplb2YodGVzdChzdGQ6OnRyYW5zZm9ybShJbkl0KCksIEluSXQoKSwgT3V0SXQoKSwgRnVuKCkpKSkgIT0gc2l6ZW9mKE5PKTsKICAgIH07CgppbnQgbWFpbigpCnsKICAgICAgICB0eXBlZGVmIHN0ZDo6dmVjdG9yPGludD46Oml0ZXJhdG9yIGl0ZXIxOwogICAgICAgIHR5cGVkZWYgc3RkOjp2ZWN0b3I8aW50Pjo6Y29uc3RfaXRlcmF0b3IgaXRlcjI7CiAgICAgICAgdHlwZWRlZiBzdGQ6OnZlY3RvcjxzdGQ6OnN0cmluZz46Oml0ZXJhdG9yIGl0ZXIzOwogICAgICAgIHR5cGVkZWYgc3RkOjpuZWdhdGU8aW50PiBmdW5jOwogICAgICAgIAogICAgICAgIGF1dG8gc3RyaW5mID0gW10oaW50KS0+c3RkOjpzdHJpbmcgeyByZXR1cm4gImhlbGxvIjsgfTsKCiAgICAgICAgc3RkOjpjb3V0IDw8ICJ2YWxpZCB0cmFuc2Zvcm0gY29tcGlsZXM6ICIgPDwgaXNfdmFsaWRfdHJhbnNmb3JtPGl0ZXIxLGl0ZXIxLGZ1bmM+Ojp2YWx1ZSA8PCBzdGQ6OmVuZGw7CiAgICAgICAgc3RkOjpjb3V0IDw8ICJpbnZhbGlkIHRyYW5zZm9ybSBjb21waWxlczogIiA8PCBpc192YWxpZF90cmFuc2Zvcm08aXRlcjEsaXRlcjIsZnVuYz46OnZhbHVlIDw8IHN0ZDo6ZW5kbDsKICAgICAgICBzdGQ6OmNvdXQgPDwgInZhbGlkIHRyYW5zZm9ybSBjb21waWxlczogIiA8PCBpc192YWxpZF90cmFuc2Zvcm08aXRlcjIsaXRlcjEsZnVuYz46OnZhbHVlIDw8IHN0ZDo6ZW5kbDsKICAgICAgICBzdGQ6OmNvdXQgPDwgImludmFsaWQgdHJhbnNmb3JtIGNvbXBpbGVzOiAiIDw8IGlzX3ZhbGlkX3RyYW5zZm9ybTxpdGVyMSxpdGVyMyxkZWNsdHlwZSgmc3RyaW5mKT46OnZhbHVlIDw8IHN0ZDo6ZW5kbDsKICAgICAgICBzdGQ6OnRyYW5zZm9ybShpdGVyMSgpLCBpdGVyMSgpLCBpdGVyMygpLCBzdHJpbmYpOwoKICAgICAgICByZXR1cm4gMDsKfQ==