This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
Having referenced this question: Can an enum class be converted to the underlying type?.
In my code I have effectively:
enum class STATE : short
{
EMPTY,
PRESENT,
PARTIAL,
};
volatile STATE state;
Then I write a typedef and a static_assert:
typedef volatile std::underlying_type<STATE> state_type;
static_assert (sizeof (state_type) == sizeof (short), "Error - unsafe for use with InterlockedCompareExchange16");
Finally I attempt to set the state with InterlockedCompareExchange16:
if (InterlockedCompareExchange16 (static_cast<state_type *>(&state), STATE::PRESENT, STATE::EMPTY) == STATE::EMPTY)
{
}
I am getting the following errors from VS2012:
My static_assert fails complaining that state_type is not the same size as short
The static_cast complains that it cannot cast from volatile STATE * to state_type *
Please can anyone give me any pointers for how to best fix my code?
From std::underlying_type:
Defines a member typedef type of type that is the underlying type for the enumeration T.
Change to:
typedef typename std::underlying_type<STATE>::type state_type;
//^^^^
A motivation for the strongly typed enum class was to prevent conversion to int, so attempting to cast to the underlying type conflicts with the intended use of the enums (see Strongly Typed Enums (revision 3)).
Instead of using OS specific threading mechanisms use std::atomic<> template that was added to c++11:
std::atomic<STATE> state(STATE::EMPTY);
STATE expected(STATE::EMPTY);
if (state.compare_exchange_strong(expected, STATE::PRESENT))
{
// 'state' set to 'PRESENT'.
}
This removes the requirement for static_assert and does not require any casting.
Related
This question already has answers here:
What are the benefits of replacing an interface argument with a type parameter?
(2 answers)
Closed 8 months ago.
In the new Type Parameters Design Draft, you can now apply an interface constraint to a generic function:
func prettyPrint[T Stringer](s T) string {
...
}
But, this was already possible by using an interface parameter without generics:
func prettyPrint(s Stringer) string {
...
}
What's the difference between using the first and using the second?
I assume the question refers to the latest draft of the Type Parameters proposal, which may end up in Go in 1.18.
The first is parametric polymorphism. The compiler verifies that the constraint is satisfied, and then generates code that takes a statically-known type. Importantly, it's not boxed.
The second is runtime polymorphism. It takes a type that's unknown at compile time (the only thing known is that it implements the interface) and works on a boxed interface pointer.
Performance considerations aside, in this simple case you can use either approach. Generics really help with the more complicated cases where the current tools don't work well.
This is a general question about symmetry between pointer and reference types in the C++ language.
Is this table of correspondence meaningful in C++ (C++11 and beyond)?
+-----------+----------------+
| Reference | Pointer |
|-----------|----------------|
| T& | T* const |
| T const& | T const* const |
| T&& | ???* |
+-----------+----------------+
and if some, what would correspond to ???* ?. (Any additional rows are missing?)
(T&& is for a concrete type T, not a deduced type. See #ComicSansMS answer for the trailing const.)
My guess it will correspond to something like std::move_iterator<T*>, but it is not a built-in language feature and it seems to create a bunch of other problems (like std::reference_wrapper does).
Is the language missing some kind of r-value pointer to be more symmetric? Or better said something that generates r-values on derreference (for example a moved object -- or a even a copy).
I know that r-value references correspond to thing that "do not have a name", however that doesn't seem to be constradictory if that samething is only obtained for a deference operation *.
NOTE 1:
I see std::move_iterator<It>::operator->() is deprecated in C++20.
Which I am not sure what it means, perhaps it means that it can't be implemented, optionally, sometimes.
This question is relevant to this deprecation because in principle std::move_iterator<It>::operator->() could return ???* rather than pointer.
(Or return move_iterator<pointer>, although that will generate a infinite regress of ->() operators... unless there is a true pointer for r-values to terminate.)
NOTE 2:
A candidate missing row missing that I can imagine is:
| void& (not a thing) | void* |
but I think it is not related to the correspondence asked in the question, but a normal irregularity of void in the language.
There is no "symmetry between pointer and reference types". Or at least, there isn't intended to be one. You can interpret the language however you like, but any symmetry you see there is accidental.
In most ways lvalue and rvalue references work the same way. The principal differences are that you can distinguish between them by type (and can therefore overload functions or affect template instantiation based on them), and they have different rules for what objects they bind, particularly under overload resolution. The purpose of the distinction is to make the type system more accurately convey the value category of the source object, so that the user can know more about what is reasonable to do with the referenced object.
Pointers don't need to do this, so they don't need to make this distinction.
Is this table of correspondence meaningful in C++ (C++11 and beyond)?
It can be a useful mental model to think of references as a syntactically different way to achieve pointer semantics.
The crucial thing missing from your table is that the equivalent to a reference is not a pointer, but a const pointer:
| Reference | Pointer |
|-----------|----------------|
| T& | T* const |
| T const& | T const* const |
Note how this is a very rough approximation of the truth that quickly breaks down. All the caveats from #Nicol Bolas's answer apply here. Also, T const& will bind to temporaries, while T const* const will very much not.
Now about the missing row for T&&. The mental model for T&& here is a reference that you are always allowed to move from. In a function body, a T&& parameter to that function can be treated exactly as if it were a T& parameter, with special semantics only kicking in when it comes to moving. For a caller of said function on the other hand, T&& is unlike any of the known reference or pointer types in that it not only will bind to unnamed temporaries (like T const& does), but it will actually only bind to temporaries and nothing else.
You may be able to figure out for yourself why the equivalent concept for a pointer, while conceivable, would not have been a very useful addition to the language.
Regarding your note 1: Deprecated means that the thing is flagged for removal from the standard. While implementations will still support it for the time being, that is purely for backwards compatibility and new code should steer clear of using deprecated functionality. The reason this functionality on move_iterator should no longer be used is exactly the absence of the concept of a pointer-that-is-safe-to-use-from from the language.
Regarding your note 2: Due to historical reasons, another crucial difference between pointers and references is that pointer types are interconvertible to some degree. That is a pointer T* can be cast to a U* even if T and U are unrelated types. This behavior is by many considered a highly dangerous legacy from C and deemed largely undesirable. References do not allow such conversions in any case. This should give you a hint as to why void& is not a valid datatype in the language.
This question already has answers here:
What is the difference between 'typedef' and 'using' in C++11?
(8 answers)
Closed 9 years ago.
I'm reading template aliases here: http://en.cppreference.com/w/cpp/language/type_alias
And I'm wondering, even if it's written on the very first line of the page I linked, what's the difference between a typedef and a type alias (using mytype = T;)
Aren't they interchangeable?
There is absolutely no difference between both.
If you take a look at the standard :
7.1.3 The typedef speciļ¬er [dcl.typedef ]
A typedef-name can also be introduced by an alias-declaration. The identifier following the using keyword becomes a typedef-name. It has the same semantics as if it were introduced by the typedef specifier. In particular, it does not define a new type and it shall not appear in the type-id.
7.3.3 The using declaration [namespace.udecl]
If a using-declaration uses the keyword typename and specifies a dependent name (14.6.2), the name introduced by the using-declaration is treated as a typedef-name.
However from this page : http://en.cppreference.com/w/cpp/language/type_alias
It is said :
Type aliases are similar to typedefs, however, have the advantage of working with templates.
It seems that this
// template type alias
template<class T> using ptr = T*;
// the name 'ptr<T>' is now an alias for pointer to T
ptr<int> x;
is only possible with the using directive.
And do not forget that this is a C++11 feature. Some compilers do not support it yet.
There is no difference.
typedef gives an alias name for the type.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
What is the value of a dialog constant DS_RECURSE (link to the official MS documentation required, historical information is welcome) ?
Thanks for attention.
DS_RECURSE doesn't exist. It was a flag in a prerelease version of Windows 95 that was removed before RTM. All the docs that refer to it talk about "Don't use it", which is now very easy to do because you can't use something that doesn't exist.
http://msdn.microsoft.com/en-us/library/aa925154.aspx
The following styles are not supported for the **style** member of the DLGTEMPLATE structure:
...
DS_RECURSE
Not required. Any child dialog box is automatically considered to be a recursive dialog box.
This is the structure:
typedef struct {
DWORD style;
DWORD dwExtendedStyle;
WORD cdit;
short x;
short y;
short cx;
short cy;
} DLGTEMPLATE;
As you see, style is DWORD so is the value of DS_RECURSE a DWORD as well.
Let it be 0 because not required.
BTW: for what reason do you need it?
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 14 years ago.
Improve this question
G'day everyone
I'm a newbie to C++ and even more so to Borland Turbo C++ Explorer. I've just encountered this compile error. Any clues as to how to fix it?
[C++ Error] comsvcs.h(3209): E2015 Ambiguity between 'ITransaction' and 'Oledb::ITransaction'
[C++ Error] comsvcs.h(3275): E2015 Ambiguity between 'ITransaction' and 'Oledb::ITransaction'
[C++ Error] comsvcs.h(16197): E2015 Ambiguity between 'ITransaction' and 'Oledb::ITransaction'
[C++ Error] comsvcs.h(16293): E2015 Ambiguity between 'ITransaction' and 'Oledb::ITransaction'
The code where the first one occurs is
EXTERN_C const IID IID_ICreateWithTransactionEx;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("455ACF57-5345-11d2-99CF-00C04F797BC9")
ICreateWithTransactionEx : public IUnknown
{
public:
virtual /* [helpstring][helpcontext] */ HRESULT STDMETHODCALLTYPE CreateInstance(
/* [in] */ ITransaction *pTransaction,
/* [in] */ REFCLSID rclsid,
/* [in] */ REFIID riid,
/* [iid_is][retval][out] */ void **pObject) = 0;
};
A couple of suggestions from another source:
As the error message of the compiler tells there are 2 declarations of the ITransaction datatype in scope of the compilation unit.
It seems the the ITransaction definition comes from Microsoft's comsvcs.h and that the OleDB::ITransaction is a implementation of the ITransaction interface from Borland. So you could try 2 things:
eliminate the OleDB::ITransaction definition (don't know Turbo C++, but there may be a component dealing with oleDB. Try to get rid of this. Or it may be included by using another #include. Search for the text oledb::ITransaction in your include directory and you will hopefully find the relevant file. Modify the include path so it is not included any more).
you could try to define CINTERFACE because the code resulting in the compile error will not be included if this is defined. But that may cause other problems...
Does anyone have any other suggestions?
Kind regards,
Bruce.
I have no clue how to do COM or what your ITransaction is, but it seems to me like your scope contains two ITransaction types. Can you be more explicit in your function prototype? Can you scope the ITransaction you want to use? Say "::ITransaction" (to use global namespace) or "some_other_namespace::ITransaction"?
Okay, we need to close this question somehow. After updating Turbo C++ Explorer with the latest patches the problem went away.
Thanks to all who offered suggestions along the way.