I want to define the following alias into the namespace Library:
namespace Library
{
template <typename T>
using MyVector = std::vector<T, std::allocator<T> >;
}
but I get the following error from the compiler:
expected unqualified-id before 'using'
I'm following the official reference on cppreference.com but so far I couldn't make it work. What am I missing?
Some programmer dude got it: C++11 was not set.
To set the proper dialect go to: Project->Properties->C/C++ Build->Settings->Tool Settings->GCC C++ Compiler->Dialect->Language Standard->ISO C++ 11
Related
CUDA 10.1
g++ 7.3
For the purposes of a unit testing suite, I need large sets of repeatable data (more than can be hard-coded). I came up with this "generator" paradigm, with the idea that it could be used to fill arbitrary containers with data.
Now I need to extend the generator to populate multivalue containers (float2, int2, thrust::complex). My solution is to use SFINAE to conditionally define a function based on whether it can be constructed from a single value or requires a pair of values.
The below code compiles fine with GCC (-std=c++1z) but fails with nvcc (-std=c++14)
#include <random>
#include <type_traits>
template <typename T>
class RandomGenerator
{
public:
RandomGenerator(T min, T max, unsigned seed = 42);
// Generate the next element in the sequence. This requires keeping all the necessary state
// to advance
T operator()();
// fill a container if it is scalar
template<typename Container>
typename std::enable_if_t<std::is_constructible_v<typename Container::value_type, T>>
fill( Container& c );
// fill a container if it takes 2 values (e.g., complex)
template<typename Container>
typename std::enable_if_t<std::is_constructible_v<typename Container::value_type, T, T>>
fill2( Container& c );
protected:
private:
std::uniform_real_distribution< T > dist;
std::mt19937 rng;
};
// Constructor - define the domain of this generation
template <typename T>
RandomGenerator<T>::RandomGenerator(T min, T max, unsigned seed)
: dist(min, max)
, rng()
{
rng.seed(seed);
}
// generate one random number
template <typename T>
T
RandomGenerator<T>::operator()()
{
return dist(rng);
}
template <typename T>
template<typename Container>
typename std::enable_if_t<std::is_constructible_v<typename Container::value_type, T>>
RandomGenerator<T>::fill( Container& c )
{
std::generate(c.begin(), c.end(), *this);
}
template <typename T>
template<typename Container>
typename std::enable_if_t<std::is_constructible_v<typename Container::value_type, T, T>>
RandomGenerator<T>::fill2( Container& c )
{
std::generate(c.begin(), c.end(), [this]() { return typename Container::value_type( (*this)(), (*this)() ); });
}
The compiler error:
/usr/local/cuda/bin/nvcc -g -Xcompiler=-fPIE -gencode=arch=compute_60,code=sm_60 --std=c++14 --use_fast_math -Xcompiler -pthread -x cu -dc unittest.cu -o unittest.cu.o
RandomGenerator.hh(30): error: namespace "std" has no member "is_constructible_v"
RandomGenerator.hh(30): error: type name is not allowed
RandomGenerator.hh(30): error: expected an identifier
RandomGenerator.hh(34): error: namespace "std" has no member "is_constructible_v"
RandomGenerator.hh(34): error: type name is not allowed
RandomGenerator.hh(34): error: too many arguments for alias template "std::enable_if_t"
RandomGenerator.hh(34): error: expected an identifier
RandomGenerator.hh(63): error: namespace "std" has no member "is_constructible_v"
RandomGenerator.hh(63): error: type name is not allowed
RandomGenerator.hh(63): error: expected an identifier
RandomGenerator.hh(71): error: namespace "std" has no member "is_constructible_v"
RandomGenerator.hh(71): error: type name is not allowed
RandomGenerator.hh(71): error: too many arguments for alias template "std::enable_if_t"
RandomGenerator.hh(71): error: expected a ";"
Am I missing something? Is there a way to pass this to CUDA?
UPDATE
It appears that the specific problem is with std::enable_if_t, std::is_XXX_v. If instead of these typdefs I use the more verbose form
typename std::enable_if<std::is_constructible<typename Container::value_type, T>::value>::type
then nvcc can handle it.
The compiler error gives you the hint that it does not know anything about std::is_constructible_v.
This is not due to the switch from gcc to nvcc but from c++17 to c++14.
You have already found out that you can use the ::value form instead and that's the way to go here. (Of course you could also expand the standard namespace if you plan to make c++17 a requirement for your project as soon as nvcc supports it.)
You can keep the std::enable_if_t though as that was already introduced in c++14.
More generally one can find that all std::something_t shortcuts are available from c++14 on but the std::something_v shortcuts were introduced in c++17.
I noticed that the following code compiles with g++/clang++-3.8 but not with nvcc:
#include <tuple> // not used, just to make sure that we have c++11
#include <stdio.h>
namespace a {
template<class T>
class X {
friend T;
};
}
I get the following compile error:
/usr/local/cuda-8.0/bin/nvcc -std=c++11 minimum_cuda_test.cu
nvcc warning : The 'compute_20', 'sm_20', and 'sm_21' architectures are deprecated, and may be removed in a future release (Use -Wno-deprecated-gpu-targets to suppress warning).
minimum_cuda_test.cu:7:10: error: ‘T’ in namespace ‘::’ does not name a type
friend T;
Interestingly, this works with nvcc:
#include <tuple> // not used, just to make sure that we have c++11
#include <stdio.h>
template<class T>
class X {
friend T;
};
Is this a bug in the compiler? I thought nvcc would internally use g++ or clang as a compiler so I am confused why this would work with my local compiler but not with nvcc.
In both cases, the code is being compiled by g++. However, when you pass a .cu file to nvcc, it puts the code through the CUDA C++ front end before passing it to the host compiler. Looking at CUDA 8 with gcc 4.8, I see that the code has been transformed from
namespace a {
template<class T>
class X {
friend T;
};
}
to
namespace a {
template< class T>
class X {
friend ::T;
};
You can see that the front end has replaced the templated friend with an equivalent, but with a prepended anonymous namespace, which is breaking the compilation. I'm not a C++ language lawyer, but this would appear to me to be a bug in the CUDA front end. I would suggest reporting it to NVIDIA.
In a very simple situation with a constrained constructor, testing for convertibility of the argument, an error is produced in clang, but not in g++:
#include <type_traits>
template <class T, class U>
constexpr bool Convertible = std::is_convertible<T,U>::value && std::is_convertible<U,T>::value;
template <class T>
struct A
{
template <class S, class = std::enable_if_t<Convertible<S,T>> >
A(S const&) {}
};
int main()
{
A<double> s = 1.0;
}
Maybe this issue is related to Is clang's c++11 support reliable?
The error clang gives, reads:
error: no member named 'value' in 'std::is_convertible<double, A<double> >'
constexpr bool Convertible = std::is_convertible<T,U>::value && std::is_convertible<U,T>::value;
~~~~~~~~~~~~~~~~~~~~~~~~~~^
I've tried
g++-5.4, g++-6.2 (no error)
clang++-3.5, clang++-3.8, clang++-3.9 (error)
with argument -std=c++1y and for clang either with -stdlib=libstdc++ or -stdlib=libc++.
Which compiler is correct? Is it a bug in clang or gcc? Or is the behavior for some reasons undefined and thus both compilers correct?
First of all, note that it works fine if you use:
A<double> s{1.0};
Instead, the error comes from the fact that you are doing this:
A<double> s = 1.0;
Consider the line below (extracted from the definition of Convertible):
std::is_convertible<U,T>::value
In your case, this is seen as it follows (once substitution has been performed):
std::is_convertible<double, A<double>>::value
The compiler says this clearly in the error message.
This is because a temporary A<double> is constructed from 1.0, then it is assigned to s.
Note that in your class template you have defined a (more or less) catch-all constructor, so a const A<double> & is accepted as well.
Moreover, remember that a temporary binds to a const reference.
That said, the error happens because in the context of the std::enable_if_t we have that A<double> is an incomplete type and from the standard we have this for std::is_convertible:
From and To shall be complete types [...]
See here for the working draft.
Because of that, I would say that it's an undefined behavior.
As a suggestion, you don't need to use std::enable_if_t in this case.
You don't have a set of functions from which to pick the best one up in your example.
A static_assert is just fine and error messages are nicer:
template <class S>
A(S const&) { static_assert(Convertible<S,T>, "!"); }
The new enum class type in C++11 came from the C++/CLI version with the same name but they are quite different and are causing me problems.
I have a library written in C++11 containing several structures like (really simplified here):
// File.h
enum class MyEnum : unsigned int
{
Val1,
Val2
};
struct MyStruct
{
MyEnum value;
MyStruct(MyEnum v) : value(v) {}
};
I am trying to reach this code from a C++/CLI class library to expose it to .NET. I include the file like this:
#pragma unmanaged
#include "File.h"
#pragma managed
The problem is that the enum constructor yields a compile error message like:
error C3821: 'v': managed type or function cannot be used in an unmanaged function
suggesting that the compiler still interprets the enum class as a C++/CLI enum class even though I am within the unmanaged section and it really should interpret it as a C++11 enum class. Is there anything I can do about this?
EDIT: I am using VS2012. Please let me know if VS2013 fixes this.
I have the same problem in VS2013. In my case, I'm including an unmanaged enum class but the compiler is generating errors because it thinks it's a managed enum class. With the help from the comments on the question, I was able to fix it by removing all forward declarations of the enum. It looks like this is a compiler bug, where the forward declaration ignores the #pragma unmanaged directive.
I've created an example of how to reproduce the bug here:
#pragma managed(push, off)
enum class TestEnum
{
One,
Two,
Three,
};
#include <vector>
enum class TestEnum; // Forward declaration after actual declaration causes the bug
#pragma managed(pop)
int main(array<System::String ^> ^args)
{
// error C3699: '&&' : cannot use this indirection on type 'TestEnum'
std::vector<TestEnum> enums;
return 0;
}
I've reported the issue to Microsoft here:
https://connect.microsoft.com/VisualStudio/feedback/details/1218131
I am working on an application(contains 3 projects, 2 in c++ and one in Objective-C) which compiles perfectly for LLVM GCC compiler. But when I switch the compiler to 'Apple LLVM compiler 3.0' I found one strange error as follow:
error: implicit instantiation of undefined template 'EList<ETemplateString<char>>'
and above error shows in the following line of code:
EList<EString> outlist;
with the forward declared EList as follows:
template <class T> class EList; // forward decls
EString is declared as follow:
typedef ETemplateString<TCHAR> EString;
and rest of the used templates are defined as:
template <class T> class ETemplateString
{
//
//
//
}
and TCHAR is declared as:
typedef char TCHAR;
can anybody please let me know why it's compiling good with GCC and throwing errors in 'Apple LLVM compiler 3.0'
See http://clang.llvm.org/compatibility.html#undep_incomplete .