Я хочу определить функцию op2()
с универсальным справочным параметром.
В зависимости от типа, я хочу различить далее, если параметр функции в op2()
является ссылкой на r-значение типа test
.
Если это так, я хочу определить тип возвращаемого значения op2
как int
.
Во всех остальных случаях тип возвращаемого значения должен быть void
.
Вот мое Я:
#include <type_traits>
#include <iostream>
#include <string>
class test {
public:
test(const std::string& str) : _str(str){}
test(test&& t) = default;
test(const test& t) = default;
friend std::ostream& operator<<(std::ostream& os, test&& t) {
os << t._str;
return os;
}
private:
std::string _str;
};
template<typename T>
void op(T&& x) {
std::cout << " is rvalue ref? " << std::is_rvalue_reference<decltype(x)>::value << std::endl;
std::cout << " is a test rvalue ref? " << std::is_same<test&&, decltype(x)>::value << std::endl;
std::cout << std::forward<T>(x) << std::endl;
}
template<typename T> // This is A
typename std::enable_if<std::negation<std::conjunction<std::is_same<test, T>, std::is_rvalue_reference<T>>>::value>::type op2(T&& x) {
std::cout << "op2: A: " << std::forward<T>(x) << std::endl;
}
template<typename T> // This is B
typename std::enable_if<std::conjunction<std::is_same<test, T>, std::is_rvalue_reference<T>>::value, int>::type op2(T&& x) {
std::cout << "op2: B: " << std::move(x) << std::endl;
return EXIT_SUCCESS;
}
int main() {
op(std::string{"r-value string"});
std::string str{"l-value string"};
op(str);
op(test{"test"});
op2(std::string{"r-value string"}); //gets into A
op2(str); //gets into A
op2(test{"r-value string"}); //Should get into B, but actually gets into A
}
Проблема с кодом заключается в том, что последний op2()
-колл переходит в неправильную перегрузку.
Я пробовал другую функцию, op()
, которая получает правильные типы с помощью decltype()
, но я не знаю, как я могу использовать decltype()
в признаке типа.
Я использую C ++ 17 с gcc8.2