I have a piece of code which does something like this:
void some_func(SomeType st) {
some_stuf...
dosomething( st.myStruct() );
some_more_stuff...
}
This SomeType::myStruct
is of type MyStruct
. This SomeType
goes through some serialization, and on the other side of communication channel I get deserialized SomeType
which is called AlmostSomeType
which has the same fields, except that myStruct
is of type std::string
(it couldn't be deserialized to MyStruct
).
MyStruct
can be created from std::string
.
Now, to not create additional versions of some_func
(DRY!) I'm going to do this:
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...
}
where getMyStruct
looks like this:
template< typename T >
T getMyStruct( T&& aT )
{ return aT; }
MyStruct getMyStruct( std::string myStructString )
{ return MyStruct( myStructString ); }
Now here's what I know/think :
AlmostSomeType
and SomeType
. MyStruct
(reference, const reference, etc), and std::string
version for strings. MyStruct
or std::string
into getMyStruct
it might pass if parameter-constructors of MyStruct
aren't explicit
. MyStruct
consisting of all the needed ctors and assignment operators, compiled code with -O2
and got the results I expected, ie no copy-ctors called. I'd like to hear your opinions if this is the right way, ie if this function template approach is OK or are there some caveats I should be aware of. I know that I'm counting a bit on compilers optimizations, but hey! You cannot depend only on language semantics.
Environment: gcc (4.7.2), -std=c++11, -O2
EDIT
Some example code I was using:
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;
}
Output I got:
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()
There is excessive copy of string (when you are passing it by value) in your solution. Why not extract special case of string and then process it separately?
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);}
I dropped some std::
prefixes here above to make code look neater.
On GCC 5.1 output is:
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()
I compiled with ~/x86-toolchain-5.1/bin/g++ mystr.cpp --std=c++14
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.