仅当没有其他转换可用时如何启用构造函数模板?
How to enable a constructor template only if no other conversion is available?
代码如下
#include <iostream>
#include <type_traits>
template <typename T>
struct bar {
bar(const bar<T>&) {
std::cout << "copy ctor\n";
}
template <typename U,
typename = std::enable_if_t<!std::is_convertible_v<U, bar<T>>>>
bar(U&&) {
std::cout << "ctor template\n";
}
};
struct foo {
operator bar<int>() const {
return bar<int>( 1 );
}
operator int() const {
return 2;
}
};
int main() {
foo my_foo;
std::cout << "constructor: ";
bar<int> my_bar( my_foo );
std::cout << "static_cast: ";
my_bar = static_cast<bar<int>>(my_foo);
}
constructor: ctor template
static_cast: ctor template
作为输出。
但是我希望 bar 的构造函数模板,即 template <typename U> bar::bar(U&&)
,仅在 U
尚未转换为 bar<T>
时才启用。在 foo
的情况下,foo::operator bar<int>() const
已经给出了这样的转换。假设我是 bar
的作者并且不了解(或影响)foo
或可能的类似 类。我怎样才能说服编译器在那种情况下使用转换运算符而不完全删除 bar
的 ctor 模板?
哦,看来已经是我想要的样子了。我只需要添加更多打印语句即可看到它:
#include <iostream>
#include <type_traits>
template <typename T>
struct bar {
bar(const bar<T>&) {
std::cout << "copy ctor\n";
}
template <typename U = T,
typename = std::enable_if_t<!std::is_convertible_v<U, bar<T>>>>
bar(U&& val) {
std::cout << "ctor template: " << val << "\n";
}
};
struct foo {
operator bar<int>() const {
std::cout << "operator bar<int>() -> ";
return bar<int>( 1 );
}
operator int() const {
std::cout << "operator int() -> ";
return 2;
}
};
int main() {
foo my_foo;
std::cout << "constructor: ";
bar<int> my_opt( my_foo );
std::cout << "static_cast: ";
my_opt = static_cast<bar<int>>(my_foo);
}
constructor: operator optional<int>() -> ctor template: 1
static_cast: operator optional<int>() -> ctor template: 1
由于 return 值优化,复制构造函数不会出现在输出中。
编辑:正如 Barry 在评论中指出的那样,这只是偶然起作用,并且可以 。
代码如下
#include <iostream>
#include <type_traits>
template <typename T>
struct bar {
bar(const bar<T>&) {
std::cout << "copy ctor\n";
}
template <typename U,
typename = std::enable_if_t<!std::is_convertible_v<U, bar<T>>>>
bar(U&&) {
std::cout << "ctor template\n";
}
};
struct foo {
operator bar<int>() const {
return bar<int>( 1 );
}
operator int() const {
return 2;
}
};
int main() {
foo my_foo;
std::cout << "constructor: ";
bar<int> my_bar( my_foo );
std::cout << "static_cast: ";
my_bar = static_cast<bar<int>>(my_foo);
}
constructor: ctor template
static_cast: ctor template
作为输出。
但是我希望 bar 的构造函数模板,即 template <typename U> bar::bar(U&&)
,仅在 U
尚未转换为 bar<T>
时才启用。在 foo
的情况下,foo::operator bar<int>() const
已经给出了这样的转换。假设我是 bar
的作者并且不了解(或影响)foo
或可能的类似 类。我怎样才能说服编译器在那种情况下使用转换运算符而不完全删除 bar
的 ctor 模板?
哦,看来已经是我想要的样子了。我只需要添加更多打印语句即可看到它:
#include <iostream>
#include <type_traits>
template <typename T>
struct bar {
bar(const bar<T>&) {
std::cout << "copy ctor\n";
}
template <typename U = T,
typename = std::enable_if_t<!std::is_convertible_v<U, bar<T>>>>
bar(U&& val) {
std::cout << "ctor template: " << val << "\n";
}
};
struct foo {
operator bar<int>() const {
std::cout << "operator bar<int>() -> ";
return bar<int>( 1 );
}
operator int() const {
std::cout << "operator int() -> ";
return 2;
}
};
int main() {
foo my_foo;
std::cout << "constructor: ";
bar<int> my_opt( my_foo );
std::cout << "static_cast: ";
my_opt = static_cast<bar<int>>(my_foo);
}
constructor: operator optional<int>() -> ctor template: 1
static_cast: operator optional<int>() -> ctor template: 1
由于 return 值优化,复制构造函数不会出现在输出中。
编辑:正如 Barry 在评论中指出的那样,这只是偶然起作用,并且可以