[英]Function for type converting or forwarding (depending on input type)
我有一段代码是这样的:
void some_func(SomeType st) {
some_stuf...
dosomething( st.myStruct() );
some_more_stuff...
}
SomeType::myStruct
的类型为MyStruct
。 这个SomeType
经历了一些序列化,并且在通信通道的另一端,我反序列化了SomeType
,它被称为AlmostSomeType
,它具有相同的字段,除了myStruct
的类型为std::string
(不能反序列MyStruct
)。
MyStruct
可以从std::string
创建。
现在,为了不创建some_func
(DRY!)的其他版本,我将这样做:
template< typename Type >
void some_func( Type type ) {
some_stuf...
dosomething( getMyStruct( type.myStruct() ) );
// or even something like:
const MyStruct& myStruct = getMyStruct( type.myStruct() );
more calls to myStruct...
some_more_stuff...
}
getMyStruct
如下所示:
template< typename T >
T getMyStruct( T&& aT )
{ return aT; }
MyStruct getMyStruct( std::string myStructString )
{ return MyStruct( myStructString ); }
现在,这就是我所知道/想的:
AlmostSomeType
和SomeType
。 MyStruct
(引用,const引用等)和std::string
版本的原因。 MyStruct
或std::string
之外的任何东西放入getMyStruct
则如果MyStruct
参数构造函数不是explicit
则它可能会通过。 MyStruct
完成了简单的测试, MyStruct
包括所有需要的MyStruct
和赋值运算符,使用-O2
编译了代码,并得到了我期望的结果,即未调用copy-ctors。 如果这是正确的方法,那么我想听听您的意见,即,如果此函数模板方法可行,或者我应该注意一些注意事项。 我知道我在指望编译器优化,但是,嘿! 您不能仅依赖语言语义。
环境:gcc(4.7.2),-std = c ++ 11,-O2
编辑
我正在使用的一些示例代码:
struct MyStruct
{
MyStruct() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
explicit MyStruct( std::string a ) : dummy_(a.size()) { std::cout << __PRETTY_FUNCTION__ << "\n"; }
MyStruct( const MyStruct& aOther ) : dummy_(aOther.dummy_) { std::cout << __PRETTY_FUNCTION__ << "\n"; }
MyStruct( MyStruct&& aOther ) : dummy_(std::move(aOther.dummy_)){ std::cout << __PRETTY_FUNCTION__ << "\n"; }
~MyStruct() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
MyStruct& operator=( const MyStruct& aOther ) { std::cout << __PRETTY_FUNCTION__ << "\n"; return *this; }
MyStruct& operator=( MyStruct&& aOther ) { std::cout << __PRETTY_FUNCTION__ << "\n"; return *this; }
double dummy_;
char cdummy_[100];
};
struct MyAggregate
{
MyStruct myStruct_;
std::string myString_;
const MyStruct& myStruct() { return myStruct_; }
const std::string& myString() { return myString_; }
MyAggregate() :myString_("four") { myStruct_.dummy_ = 5.5; }
};
int main()
{
MyAggregate myAggregate;
std::cout << "---\n";
const MyStruct& ms1 = getMyStruct( myAggregate.myStruct_ );
std::cout << "---\n";
const MyStruct& ms2 = getMyStruct( myAggregate.myString_ );
std::cout << "---\n";
const MyStruct& ms3 = getMyStruct( myAggregate.myStruct() );
std::cout << "---\n";
const MyStruct& ms4 = getMyStruct( myAggregate.myString() );
std::cout << "---\n";
return 0;
}
我得到的输出:
MyStruct::MyStruct()
---
T getMyStruct(T&&) [with T = MyStruct&]
---
MyStruct getMyStruct(std::string)
MyStruct::MyStruct(std::string)
---
T getMyStruct(T&&) [with T = const MyStruct&]
---
MyStruct getMyStruct(std::string)
MyStruct::MyStruct(std::string)
---
MyStruct::~MyStruct()
MyStruct::~MyStruct()
MyStruct::~MyStruct()
解决方案中有过多的字符串副本(当您按值传递时)。 为什么不提取字符串的特殊情况然后分开处理呢?
template<typename T, typename =
typename enable_if<!is_same<decay_t<T>,string>::value>::type >
decltype(auto) getMyStruct( T&& aT )
{ return aT; }
template<typename T, typename =
typename enable_if<is_same<decay_t<T>,string>::value>::type >
MyStruct getMyStruct (T &&aT)
{ return MyStruct (aT);}
我在上面放了一些std::
前缀,使代码看起来更整洁。
在GCC 5.1上,输出为:
MyStruct::MyStruct()
---
decltype(auto) getMyStruct(T&&) [with T = MyStruct&; <template-parameter-1-2> = void]
---
MyStruct getMyStruct(T&&) [with T = std::__cxx11::basic_string<char>&; <template-parameter-1-2> = void]
MyStruct::MyStruct(std::__cxx11::string)
---
decltype(auto) getMyStruct(T&&) [with T = const MyStruct&; <template-parameter-1-2> = void]
---
MyStruct getMyStruct(T&&) [with T = const std::__cxx11::basic_string<char>&; <template-parameter-1-2> = void]
MyStruct::MyStruct(std::__cxx11::string)
---
MyStruct::~MyStruct()
MyStruct::~MyStruct()
MyStruct::~MyStruct()
我用~/x86-toolchain-5.1/bin/g++ mystr.cpp --std=c++14
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.